对简单工厂模式、工厂方法模式的思考
目录
- 1 背景
- 1.1 题目描述
- 1.2 输入描述
- 1.3 输出描述
- 1.4 输入示例
- 1.5 输出示例
- 2 简单工厂模式
- 3 工厂方法模式
- 4 思考
- 4.1 改进工厂方法模式
1 背景
题目源自:【设计模式专题之工厂方法模式】2.积木工厂
1.1 题目描述
小明家有两个工厂,一个用于生产圆形积木,一个用于生产方形积木,请你帮他设计一个积木工厂系统,记录积木生产的信息。
1.2 输入描述
输入的第一行是一个整数 N(1 ≤ N ≤ 100),表示生产的次数。
接下来的 N 行,每行输入一个字符串和一个整数,字符串表示积木的类型。积木类型分为 “Circle” 和 “Square” 两种。整数表示该积木生产的数量
1.3 输出描述
对于每个积木,输出一行字符串表示该积木的信息。
1.4 输入示例
3
Circle 1
Square 2
Circle 1
1.5 输出示例
Circle Block
Square Block
Square Block
Circle Block
2 简单工厂模式
- 一个工厂生产多个对象。
- (1)抽象对象【通过接口进行抽象】
- (2)具体对象【通过类实现接口】
- (3)具体工厂
- 代码示例:
public class Main {public static void main(String[] args) {ShapeFactorySystem shapeFactorySystem = new ShapeFactorySystem(new SimpleShapeFactory());Scanner scanner = new Scanner(System.in);int count = Integer.parseInt(scanner.nextLine());for (int i = 0; i < count; i++) {String line = scanner.nextLine();String[] parts = line.split(" ");String type = parts[0];shapeFactorySystem.produce(type, Integer.parseInt(parts[1]));}}
}interface Shape {void draw(int n);
}class Circle implements Shape {public void draw(int n) {for (int i = 0; i < n; i++) {System.out.println("Circle Block");}}
}class Square implements Shape {@Overridepublic void draw(int n) {for (int i = 0; i < n; i++) {System.out.println("Square Block");}}
}class SimpleShapeFactory {public Shape createShape(String type) {if ("Circle".equals(type)) {return new Circle();} else if ("Square".equals(type)) {return new Square();} else {throw new RuntimeException("Unknown type");}}
}class ShapeFactorySystem {private SimpleShapeFactory simpleShapeFactory;public ShapeFactorySystem(SimpleShapeFactory simpleShapeFactory) {this.simpleShapeFactory = simpleShapeFactory;}public void produce(String type, int n) {Shape shape = simpleShapeFactory.createShape(type);shape.draw(n);}
}
3 工厂方法模式
- 和简单工厂不同的是,不同对象的生产工厂也不同。
- 代码示例:
public class Main {public static void main(String[] args) {ShapeFactorySystem shapeFactorySystem = new ShapeFactorySystem(new CircleFactory(), new SquareFactory());Scanner scanner = new Scanner(System.in);int count = Integer.parseInt(scanner.nextLine());for (int i = 0; i < count; i++) {String line = scanner.nextLine();String[] parts = line.split(" ");String type = parts[0];shapeFactorySystem.produce(type, Integer.parseInt(parts[1]));}}
}interface Shape {void draw(int n);
}class Circle implements Shape {public void draw(int n) {for (int i = 0; i < n; i++) {System.out.println("Circle Block");}}
}class Square implements Shape {@Overridepublic void draw(int n) {for (int i = 0; i < n; i++) {System.out.println("Square Block");}}
}interface ShapeFactory {Shape createShape(String type);
}class CircleFactory implements ShapeFactory {@Overridepublic Shape createShape(String type) {return new Circle();}
}class SquareFactory implements ShapeFactory {@Overridepublic Shape createShape(String type) {return new Square();}
}class ShapeFactorySystem {private ShapeFactory circleFactory;private ShapeFactory squareFactory;public ShapeFactorySystem(ShapeFactory circleFactory, ShapeFactory squareFactory) {this.circleFactory = circleFactory;this.squareFactory = squareFactory;}public void produce(String type, int n) {Shape shape;if ("Circle".equals(type)) {shape = circleFactory.createShape(type);} else if ("Square".equals(type)) {shape = squareFactory.createShape(type);} else {throw new RuntimeException("Unknown type");}shape.draw(n);}
}
4 思考
- 从这个例子中,看不出工厂方法模式比简单工厂模式好在哪里。
- 假设需求变化了,需要增加一种类型,那么,对于简单工厂模式,只要修改:
// 新增类
class xxx implements Shape {@Overridepublic void draw(int n) {for (int i = 0; i < n; i++) {System.out.println("xxx Block");}}
}// 修改方法
class SimpleShapeFactory {public Shape createShape(String type) {if ("Circle".equals(type)) {return new Circle();} else if ("Square".equals(type)) {return new Square();} else if (xxx.equals(type)) {...} else {throw new RuntimeException("Unknown type");}}
}
- 但是对应用层代码(main方法)不需要做任何改动。这反而更好。
- 对于简单工厂模式,要修改:
// 修改应用层代码
public static void main(String[] args) {ShapeFactorySystem shapeFactorySystem = new ShapeFactorySystem(new CircleFactory(), new SquareFactory(), xxx);Scanner scanner = new Scanner(System.in);int count = Integer.parseInt(scanner.nextLine());for (int i = 0; i < count; i++) {String line = scanner.nextLine();String[] parts = line.split(" ");String type = parts[0];shapeFactorySystem.produce(type, Integer.parseInt(parts[1]));}
}// 新增类
class xxx implements Shape {@Overridepublic void draw(int n) {for (int i = 0; i < n; i++) {System.out.println("xxx Block");}}
}// 新增类
class xxxFactory implements ShapeFactory {...
}class ShapeFactorySystem {private ShapeFactory circleFactory;private ShapeFactory squareFactory;private xxxFactory ...;public ShapeFactorySystem(ShapeFactory circleFactory, ShapeFactory squareFactory, xxxFactory ...) {this.circleFactory = circleFactory;this.squareFactory = squareFactory;...}public void produce(String type, int n) {Shape shape;if ("Circle".equals(type)) {shape = circleFactory.createShape(type);} else if ("Square".equals(type)) {shape = squareFactory.createShape(type);} else if (xxx) {...} else {throw new RuntimeException("Unknown type");}shape.draw(n);}
}
- 真麻烦啊。
4.1 改进工厂方法模式
- 代码示例:
public class Main {public static void main(String[] args) {ShapeFactorySystem shapeFactorySystem = ShapeFactorySystem.getSingleton();Scanner scanner = new Scanner(System.in);int count = Integer.parseInt(scanner.nextLine());for (int i = 0; i < count; i++) {String line = scanner.nextLine();String[] parts = line.split(" ");String type = parts[0];shapeFactorySystem.produce(type, Integer.parseInt(parts[1]));}}
}interface Shape {void draw(int n);
}class Circle implements Shape {public void draw(int n) {for (int i = 0; i < n; i++) {System.out.println("Circle Block");}}
}class Square implements Shape {@Overridepublic void draw(int n) {for (int i = 0; i < n; i++) {System.out.println("Square Block");}}
}interface ShapeFactory {Shape createShape();
}class CircleFactory implements ShapeFactory {@Overridepublic Shape createShape() {return new Circle();}
}class SquareFactory implements ShapeFactory {@Overridepublic Shape createShape() {return new Square();}
}class ShapeFactorySystem {private static final Map<ShapeType, ShapeFactory> shapeFactoryMap = new HashMap<>();private static ShapeFactorySystem shapeFactorySystem;private ShapeFactorySystem() {shapeFactoryMap.put(ShapeType.CIRCLE, new CircleFactory());shapeFactoryMap.put(ShapeType.SQUARE, new SquareFactory());}public static ShapeFactorySystem getSingleton() {if (shapeFactorySystem == null) {synchronized (ShapeFactorySystem.class) {if (shapeFactorySystem == null) {shapeFactorySystem = new ShapeFactorySystem();}}}return shapeFactorySystem;}private ShapeFactory acquireShapeFactory(ShapeType type) {return shapeFactoryMap.get(type);}public void produce(String type, int n) {ShapeFactory shapeFactory = acquireShapeFactory(ShapeType.of(type));Shape shape = shapeFactory.createShape();shape.draw(n);}
}enum ShapeType {CIRCLE("Circle"), SQUARE("Square");private String value;private ShapeType(String value) {this.value = value;}private String getValue() {return value;}public static ShapeType of(String value) {for (ShapeType shapeType : ShapeType.values()) {if (shapeType.getValue().equals(value)) {return shapeType;}}// 如果没有找到匹配的枚举对象,可以抛出一个异常或返回nullthrow new IllegalArgumentException("Unknown ShapeType: " + value);}
}
多线程场景下,不能用HashMap。
- 如果新增一种类型:
// 新增类
class xxx implements Shape {@Overridepublic void draw(int n) {for (int i = 0; i < n; i++) {System.out.println("xxx Block");}}
}// 新增类
class xxxFactory implements ShapeFactory {@Overridepublic Shape createShape() {return new xxx();}
}// 修改方法(不修改之前代码,新增语句)
private ShapeFactorySystem() {shapeFactoryMap.put(ShapeType.CIRCLE, new CircleFactory());shapeFactoryMap.put(ShapeType.SQUARE, new SquareFactory());
}// 不修改之前的代码,加一个枚举对象
enum ShapeType {CIRCLE("Circle"), SQUARE("Square"), xxx;...
}
- 当然了,通过map + enum这种改进也可以应用到简单工厂模式中。
- 不过,当创建对象变得复杂时,简单工厂模式就难以应用对了:
class SimpleShapeFactory {public Shape createShape(String type) {if ("Circle".equals(type)) {return new Circle(); // 简单对象} else if ("Square".equals(type)) {return new Square(); // 简单对象} else {throw new RuntimeException("Unknown type");}}
}
相关文章:
对简单工厂模式、工厂方法模式的思考
目录 1 背景1.1 题目描述1.2 输入描述1.3 输出描述1.4 输入示例1.5 输出示例 2 简单工厂模式3 工厂方法模式4 思考4.1 改进工厂方法模式 1 背景 题目源自:【设计模式专题之工厂方法模式】2.积木工厂 1.1 题目描述 小明家有两个工厂,一个用于生产圆形积木…...

【详识JAVA语言】面向对象程序三大特性之二:继承
继承 为什么需要继承 Java中使用类对现实世界中实体来进行描述,类经过实例化之后的产物对象,则可以用来表示现实中的实体,但是 现实世界错综复杂,事物之间可能会存在一些关联,那在设计程序是就需要考虑。 比如&…...

【剑指offer--C/C++】JZ3 数组中重复的数字
一、题目 二、本人思路及代码 这道题目它要求的时间空间利用率都是n,那么可以考虑创建一个长度为n的数组repeat初始化为0,下标代码出现的数字,下标对应的数组内容代表该下标数字出现的次数。然后遍历提供的数组,每出现一个数字&a…...
基于SpringBoot的在线拍卖系统设计与实现(源码)
项目源码:https://gitee.com/oklongmm/biye2 引言 随着互联网技术的发展,电子商务得以快速发展,其中之一的在线拍卖系统也逐渐得到了广泛的应用。但是,现有的在线拍卖系统在操作复杂性、安全性和稳定性方面存在一定的问题。为了…...
卢森堡比利时土耳其媒体宣发稿助力跨境出海推广新闻营销
【本篇由言同数字科技有限公司原创】随着全球化进程的加速,越来越多的品牌开始考虑在海外市场扩展业务。对于品牌来说,跨境海外推广是必要的,因为它可以帮助品牌打开更大的市场、吸引更多的消费者、提高品牌知名度和形象,并在全球…...

冒泡排序(C语言详解)
原理:从左到右一次比较,如果左侧数字比右侧数字大(小),则两数交换,否则比较下一 组数字,每一次大循环比较可以将乱序的最右侧数字改为最大(最小),…...

STC-ISP原厂代码研究之 V3.7d汇编版本
最近在研究STC的ISP程序,用来做一个上位机烧录软件,逆向了上位机软件,有些地方始终没看明白,因此尝试读取它的ISP代码,但是没有读取成功。应该是目前的芯片架构已经将引导代码放入在了单独的存储块中,而这存储块有硬件级的使能线,在面包板社区-宏晶STC单片机的ISP的BIN文…...

【word】引用文献如何标注右上角
一、在Word文档中引用文献并标注在右上角的具体步骤如下 1、将光标移动到需要添加文献标注的位置: 2、在文档上方的工具栏中选择“引用”选项: 3、点击“插入脚注”或“插入尾注”: ①如果选择的是脚注,则脚注区域会出现在本页的…...
MySQL 5.5、5.6、5.7的主从复制改进
主从复制面临的问题 MySQL一直以来的主从复制都是被诟病,原因是: 1、主从复制效率低 早期mysql的复制是通过将binlog语句异步推送到从库。从库启动一个IO线程将接收到的数据记录到relaylog中;另外启动一个SQL线程负责顺序执行relaylog中的语句实现对数据的拷贝。 这里的…...

性能分析排查思路之日志(1)
本文是性能问题分析排查思路的展开内容之一,主要分为日志1期,机器4期、环境2期共7篇系列文章,本期是第一篇,讲日志的分析方法和经验。 系列文章传送门: 一图梳理性能问题分析排查思路-总体概述(0ÿ…...

Vue中如何实现条件渲染?
在Vue中实现条件渲染非常简单且灵活,主要通过Vue的指令来实现。在Vue中,我们可以使用v-if和v-else指令来根据条件来渲染不同的内容。下面就让我们通过一个简单的示例来演示如何在Vue中实现条件渲染: <!DOCTYPE html> <html lang&qu…...

Postman上传文件的操作方法
前言 调用某个接口,测试上传文件功能。一时间不知如何上传文件,本文做个操作记录,期望与你有益。 步骤一、设置Headers key:Content-Type value:multipart/form-data 步骤二、设置Body 选择form-data key:file下拉框选择file类型value&…...
linux系统Jenkins工具介绍
Jenkins概念介绍 Jenkins概念Jenkins目的特性产品发布流程 Jenkins概念 Jenkins是一个功能强大的应用程序,允许持续集成和持续交付项目,无论用的是什么平台。这是一个免费的源代码,可以处理任何类型的构建或持续集成。集成Jenkins可以用于一些…...

【python】遵守 robots.txt 规则的数据爬虫程序
程序1 编写一个遵守 robots.txt 规则的数据爬虫程序涉及到多个步骤,包括请求网页、解析 robots.txt 文件、扫描网页内容、存储数据以及处理异常。由于编程语言众多,且每种语言编写爬虫程序的方式可能有所不同,以下将使用 Python 语言举例&am…...
使用爬虫去获取四六级成绩
使用爬虫去获取四六级成绩 今天出成绩,没过,二战六级依然惨死,那么我就写一个简单的爬虫,其实也可以封装成一个接口的,然后直接输入姓名 身份证好 以及四六级即可获取成绩,我就是简单的玩了一下哈…...
洛谷P1256 显示图像
广搜练手题 题目链接 思路 打印每个数与其最近的 1 1 1的曼哈顿距离,显然广搜,存储每一个 1 1 1,针对每一个 1 1 1开始广搜,逐层更新,每轮后更新的为两轮之中的最小曼哈顿距离 ACcode #include<bits/stdc.h>…...

模拟器抓HTTP/S的包时如何绕过单向证书校验(XP框架)
模拟器抓HTTP/S的包时如何绕过单向证书校验(XP框架) 逍遥模拟器无法激活XP框架来绕过单向的证书校验,如下图: 解决办法: 安装JustMePlush.apk安装Just Trust Me.apk安装RE管理器.apk安装Xposedinstaller_逍遥64位…...

【JS 算法题: 将 json 转换为字符串】
题目简介 其实就是手撕 JSON.stringfy()。 算法实现 输入 原则上来说,输入的是一个 json 对象。但需要考虑到异常情况,即输入了其它类型的数据,比如:12, true, ‘abc’, [‘red’, ‘green’], null, undefined 等。 输出 …...

数的范围 刷题笔记
思路 寻找第一个大于等于目标的 数 因为该数组是升序的 所以 我们可以采用二分的方式 逼近答案 定义一个左指针和一个右指针 当左右指针重合时 就是我们要找的答案 当我们寻找第一个大于等于x的数时 a[mid]>x,答案在mid处 或者在mid的左边 因此让rmid继续逼近 如果…...

XSS简介及xsslabs第一关
XSS被称为跨站脚本攻击(Cross-site scripting),由于和CSS(CascadingStyle Sheets)重名,所以改为XSS。 XSS主要速于javascript语言完成恶意的攻击行为,因为javascript可非常灵活的操作html、css和浏览器 XSS就是指通过利用网页开发时留下的漏…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...

大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...