對簡單工廠模式、工廠方法模式的思考

目錄

  • 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.pswp.cn/news/717910.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/717910.shtml
英文地址,請注明出處:http://en.pswp.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…