对简单工厂模式、工厂方法模式的思考

目录

  • 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");}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/717910.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

铁路关基保护新规发布!铁路软件供应链安全洞察与治理思路

近日&#xff0c;国家铁路局发布《铁路关键信息基础设施安全保护管理办法》&#xff0c;《办法》第十四条提到&#xff1a;“运营者应当加强铁路关键信息基础设施供应链安全保护&#xff0c;优先采购安全可信的网络产品和服务。运营者采购网络产品和服务&#xff0c;应当预判该…

Intel FPGA IP之LVDS SerDes IP学习

FPGA 视频数据输入输出直通工程&#xff1a; 屏&#xff1a;13.2吋8bit色深&#xff0c;屏幕分辨率为1440*192060&#xff0c;具有两个Port&#xff0c;每个Port有4个差分数据对与1个差分时钟对&#xff0c;差分对均支持LVDS协议芯片&#xff1a;Cyclone V系列FPGA目的&#x…

标签转格式问题之——xml_2_txt.py

import xml.etree.ElementTree as ET#xml 是python自带的package import osclasses[walnut]#写自己的分类名 pre_dirF:/2023walnut/labels#xml文件所在文件夹 target_dirF:/2023walnut/yolo#想要存储txt文件的文件夹 pathos.listdir(pre_dir)for path1 in path: # path1rC:\Use…

[变压器故障诊断分类及预测】基于Elman神经网络

课题名称&#xff1a;基于Elman神经网络的变压器故障诊断分类及预测 版本日期&#xff1a;2024-02-10 运行方式&#xff1a;直接运行Elman0507.m文件 代码获取方式&#xff1a;私信博主或QQ&#xff1a;491052175 模型描述&#xff1a; 对变压器油中溶解气体进行分析是变压…

Noise Conditional Score Networks(NCSN)学习

参考&#xff1a; [1] https://zhuanlan.zhihu.com/p/597490389 [2] https://www.zhangzhenhu.com/aigc/Score-Based_Generative_Models.html TOC 1 基于分数的生成模型1.1 简介和动机1.2 Score Matching及其改进1.2.1 Score Matching1.2.2 Sliced score matching&#xff08;不…

XSS_lab(level1-level5)

level1 直接输入页面没有发现输入框&#xff0c;观察url发现有传参 尝试修改传参为&#xff1a;<script>alert(1)</script> 过啦&#xff01; level2 页面中有输入框&#xff0c;尝试构建语句&#xff1a;<script>alert(1)</script>,传输后查看源代…

国际心理学导师-叶子文JeffreyYip的《意识地图》

“物质就是能量。” ---爱因斯坦 “時常保持觉知&#xff0c;有意识地发现情绪起伏 你随时都能翻转人生 做自己人生的导演 当你频率高时&#xff0c;万事万物为你而来” ---大卫霍金斯 叶子文-《意识地图》&#xff1a;高阶心理学课程 宇宙间万物的本质是能量。一切都靠能量…

Java基础---lambda表达式

一、为什么要引入lambda表达式 lambda 表达式是一个可传递的代码块 &#xff0c; 可以在以后执行一次或多次 。 在介绍lambda表达式之前&#xff0c;我们看一下&#xff0c;以前&#xff0c;我们对于一个问题的通常写法。 假设你已经了解了如何按指定时间间隔完成工作&#xf…

js字符串转json的3种方法

1.eval方式解析 function strToJson(str){var json eval("(" str ")");return json;}console.log(strToJson("{int:1, string:demo}")); 运行截图&#xff1a; 注&#xff1a; 记得别忘了str两旁的小括号。 永远不要使用 eval !!! eval() 是一…

611. 有效三角形的个数 - 力扣

1. 题目 给定一个包含非负整数的数组 nums &#xff0c;返回其中可以组成三角形三条边的三元组个数。 2. 示例 3. 分析 利用已升序了的数组通过 a b > c 这条公式找出符合要求的三元组&#xff0c;利用这个公式的前提是三条边为从小到大&#xff0c;再利用单调性快速统计…

STM32 (1)

1.基本信息 stm32是由ST公司生产的一种32位微控制器&#xff08;单片机&#xff09;。 1.1 各种型号 stm32是32位单片机的总称&#xff0c;有多种不同的系列。 32即用32个比特位表示一个地址&#xff0c;寻址范围&#xff1a;0x00000000 --0xffffffff (4GB) 1.2 存储密度 …

Mysql事务的两段式提交

binlog和redo log区别 为了满足Mysql的事物ACID特性&#xff0c;InnoDB引入了redo log和 undo log日志文件。为了满足主从同步Mysql引入了binlog日志文件。redo log和binlog文件都保存的数据库对数据库的修改&#xff0c;但是binlog和redo log本质上是不一样的&#xff1a; r…

UE5中实现后处理深度描边

后处理深度描边可以通过取得边缘深度变化大的区域进行描边&#xff0c;一方面可以用来做角色的等距内描边&#xff0c;避免了菲尼尔边缘光不整齐的问题&#xff0c;另一方面可以结合场景扫描等特效使用&#xff0c;达到更丰富的效果&#xff1a; 后来解决了开启TAA十字线和锯齿…

XXL-Job的基本使用

一、市面上常见的任务调度产品 针对分布式任务调度的需求&#xff0c;市场上出现了很多的产品: 其中XXL-job 是我们经常使用的任务调度平台,XXL这三个英文字母.是以作者名许雪里命名的。 可以前往 Gitee 地址进行下载使用 https://gitee.com/xuxueli0323/xxl-job.git二、XXL-J…

使用`paddle.nn.Layer`自定义网络教程

文章目录 使用paddle.nn.Layer自定义网络教程1. 概念介绍2. 数据处理3. 搭建一个完整的深度学习网络4. 使用paddle.nn.Layer构建深度学习网络5. 利用paddle.nn.Layer进行子层的访问6. 修改paddle.nn.Layer层的成员变量7. 存储模型的参数8. 总结 使用paddle.nn.Layer自定义网络教…

LockBit病毒入侵揭秘:如何防范与应对

在数字时代&#xff0c;随着科技的飞速发展&#xff0c;网络安全问题愈发凸显。恶意软件和勒索软件等网络威胁正不断演变&#xff0c;其中一款备受关注的勒索软件就是LockBit。本文将深入介绍LockBit的特征、攻击手段、演进历程以及对网络安全的威胁。 01 主要特征 LockBit是…

算法知识(java)随笔

1: 保留指定的小数为 printf("%.2f\n", ret) 和c语言类似 // 怎么保留小数 System.out.printf("%.2f\n", 1.0/3); 2: 在写小数二分的时候 加入让结果保留6位数 那么 while(r - l > 1e-8) 3: java Map里面之前写的代码: /*** 也就是 统计x在map里面的…

第二十一周周报

文献阅读&#xff1a;Recent Advances of Monocular 2D and 3D Human Pose Estimation: A Deep Learning Perspective 摘要&#xff1a;在本文中&#xff0c;作者提供了一个全面的 2d到3d视角来解决单目人体姿态估计的问题。首先&#xff0c;全面总结了人体的二维和三维表征。…

腾讯云Windows轻量应用服务器的默认密码是什么,以及如何重置?

首先&#xff0c;腾讯云轻量应用服务器的默认用户名是没有设置密码的&#xff0c;首次登录时需要重置密码。这意味着如果你的轻量应用服务器是腾讯云的&#xff0c;那么默认密码是不存在的&#xff0c;需要通过重置密码来获得一个新的密码。 关于如何重置密码&#xff0c;有几…

chatgpt新版本api的调用

chatgpt新版本api的调用 原始版本调用api方式&#xff1a;新版调用chatgpt-api的方式&#xff1a; 原始版本调用api方式&#xff1a; import openaiopenai.api_key "{上面复制的key}"completion openai.ChatCompletion.create(model"gpt-3.5-turbo",mes…