Java設計模式-工廠模式

目錄

一、簡單工廠模式

(一)需求

(二)使用傳統的方法來完成

(三)傳統方法的優缺點

(四)基本介紹

(五)使用簡單工廠模式

二、工廠方法模式

(一)需求

(二)思路

(三)基本介紹

(四)工廠方法模式應用

三、抽象工廠模式

(一)基本介紹

(二)應用實例


一、簡單工廠模式

(一)需求

看一個披薩的項目:要便于披薩種類的擴展,要便于維護
  1. 披薩的種類很多(比如 GreekPizzCheesePizz )
  2. 披薩的制作有 preparebake, cut, box
  3. 完成披薩店訂購功能。

(二)使用傳統的方法來完成

1、類圖

2、代碼

pizza類

//將Pizza 類做成抽象
public abstract class Pizza {protected String name; //名字//準備原材料, 不同的披薩不一樣,因此,我們做成抽象方法public abstract void prepare();public void bake() {System.out.println(name + " baking;");}public void cut() {System.out.println(name + " cutting;");}//打包public void box() {System.out.println(name + " boxing;");}public void setName(String name) {this.name = name;}
}

?兩種pizza

public class GreekPizza extends Pizza {@Overridepublic void prepare() {// TODO Auto-generated method stubSystem.out.println(" 給希臘披薩 準備原材料 ");}}=========================================================
public class CheesePizza extends Pizza {@Overridepublic void prepare() {// TODO Auto-generated method stubSystem.out.println(" 給制作奶酪披薩 準備原材料 ");}
}

編寫OrderPizza去訂購需要的各種pizza

public class OrderPizza {// 構造器public OrderPizza() {Pizza pizza = null;String orderType; // 訂購披薩的類型do {orderType = getType();if (orderType.equals("greek")) {pizza = new GreekPizza();pizza.setName(" 希臘披薩 ");} else if (orderType.equals("cheese")) {pizza = new CheesePizza();pizza.setName(" 奶酪披薩 ");} else if (orderType.equals("pepper")) {pizza = new PepperPizza();pizza.setName("胡椒披薩");} else {break;}//輸出pizza 制作過程pizza.prepare();pizza.bake();pizza.cut();pizza.box();} while (true);}
}

客戶端訂購pizza

//相當于一個客戶端,發出訂購
public class PizzaStore {public static void main(String[] args) {// TODO Auto-generated method stubnew OrderPizza();}}

(三)傳統方法的優缺點

1) 優點是比較好理解,簡單易操作。
2) 缺點是違反了設計模式的 ocp 原則,即 對擴展開放,對修改關閉 。即當我們給類增加新功能的時候,盡量不修改代碼,或者盡可能少修改代碼.
3) 比如我們這時要新增加一個 Pizza 的種類 (Pepper 披薩 ) ,我們需要做如下修改 .

4) 改進的思路分析
分析: 修改代碼可以接受,但是如果我們在其它的地方也有創建 Pizza 的代碼,就意味著,也需要修改,而創建Pizza 的代碼, 往往有多處
思路: 把創建 Pizza 對象封裝到一個類中,這樣我們有新的 Pizza 種類時,只需要修改該類就可, 其它有創建到 Pizza 對象的代碼就不需要修改了 .-> 簡單工廠模式

(四)基本介紹

  1. 簡單工廠模式是屬于創建型模式,是工廠模式的一種。簡單工廠模式是由一個工廠對象決定創建出哪一種產品類的實例。簡單工廠模式是工廠模式家族中最簡單實用的模式
  2. 簡單工廠模式:定義了一個創建對象的類,由這個類來封裝實例化對象的行(代碼)
  3. 在軟件開發中,當我們會用到大量的創建某種、某類或者某批對象時,就會使用到工廠模式

在簡單工廠模式中,主要涉及三個角色:抽象產品、具體產品和簡單工廠。

抽象產品:抽象產品可以是一個接口或抽象類,定義了產品通用的方法,有具體子類來實現

具體產品:具體產品是抽象產品的實現類,它實現了抽象產品中定義的方法

簡單工廠:包含創建對象的方法,隱藏了創建對象細節。

(五)使用簡單工廠模式

簡單工廠模式的設計方案 : 定義一個可以實例化 Pizaa 對象的類,封裝創建對象的代碼。

將對象的創建邏輯封裝在一個工廠類中,客戶端不需要知道具體的創建細節,只需要向工廠類請求所需對象即可。

簡單工廠類,封裝了創建對象的方法

//簡單工廠類,封裝了創建對象的細節
public class SimpleFactory {//根據orderType 返回對應的Pizza 對象public Pizza createPizza(String orderType) {Pizza pizza = null;System.out.println("使用簡單工廠模式");if (orderType.equals("greek")) {pizza = new GreekPizza();pizza.setName(" 希臘披薩 ");} else if (orderType.equals("cheese")) {pizza = new CheesePizza();pizza.setName(" 奶酪披薩 ");} else if (orderType.equals("pepper")) {pizza = new PepperPizza();pizza.setName("胡椒披薩");}return pizza;}}

orderpizza

public class OrderPizza {//定義一個簡單工廠對象SimpleFactory simpleFactory;Pizza pizza = null;//構造器public OrderPizza(SimpleFactory simpleFactory) {setFactory(simpleFactory);}public void setFactory(SimpleFactory simpleFactory) {String orderType = ""; //用戶輸入的this.simpleFactory = simpleFactory; //設置簡單工廠對象do {orderType = getType(); pizza = this.simpleFactory.createPizza(orderType);//輸出pizzaif(pizza != null) { //訂購成功pizza.prepare();pizza.bake();pizza.cut();pizza.box();} else {System.out.println(" 訂購披薩失敗 ");break;}}while(true);}// 寫一個方法,可以獲取客戶希望訂購的披薩種類private String getType() {try {BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));System.out.println("input pizza 種類:");String str = strin.readLine();return str;} catch (IOException e) {e.printStackTrace();return "";}}}

客戶端下單

//相當于一個客戶端,發出訂購
public class PizzaStore {public static void main(String[] args) {//使用簡單工廠模式new OrderPizza(new SimpleFactory());System.out.println("~~退出程序~~");}}

其實工廠模式還叫靜態工廠模式,也就是把創建對象的方法設置為靜態方法,那就不需要創建工廠對象了,直接用類名的方式調用工廠創建對象的方法即可。


//簡單工廠類,封裝了創建對象的細節
public class SimpleFactory {//簡單工廠模式 也叫 靜態工廠模式public static Pizza createPizza(String orderType) {Pizza pizza = null;System.out.println("使用簡單工廠模式2");if (orderType.equals("greek")) {pizza = new GreekPizza();pizza.setName(" 希臘披薩 ");} else if (orderType.equals("cheese")) {pizza = new CheesePizza();pizza.setName(" 奶酪披薩 ");} else if (orderType.equals("pepper")) {pizza = new PepperPizza();pizza.setName("胡椒披薩");}return pizza;}}

orderpizza

public class OrderPizza2 {Pizza pizza = null;String orderType = "";// 構造器public OrderPizza2() {do {orderType = getType();pizza = SimpleFactory.createPizza2(orderType);// 輸出pizzaif (pizza != null) { // 訂購成功pizza.prepare();pizza.bake();pizza.cut();pizza.box();} else {System.out.println(" 訂購披薩失敗 ");break;}} while (true);}// 寫一個方法,可以獲取客戶希望訂購的披薩種類private String getType() {try {BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));System.out.println("input pizza 種類:");String str = strin.readLine();return str;} catch (IOException e) {e.printStackTrace();return "";}}
}

總結:工廠封裝了對象的創建過程,降低了客戶端的復雜性,并且方便了產品類型的擴展和維護。

二、工廠方法模式

(一)需求

披薩項目新的需求:客戶在點披薩時,可以點不同口味的披薩,比如 北京的奶酪 pizza 、 北京的胡椒pizza 或者是倫敦的奶酪 pizza 、倫敦的胡椒 pizza

(二)思路

思路1

使用簡單工廠模式,創建不同的簡單工廠類,比如 BJPizzaSimpleFactory 、LDPizzaSimpleFactory 等等 . 從當前這個案例來說,也是可以的,但是考慮到項目的規模,以及軟件的可維護性、可擴展性并不是特別好
思路2
使用工廠方法模式

(三)基本介紹

工廠方法模式設計方案 :將披薩項目的實例化功能抽象成抽象方法,在不同的口味點餐子類中具體實現。
工廠方法模式 :抽象工廠中定義了一個創建對象的抽象方法,由子類工廠決定要實例化的類。工廠方法模式將 對象的實例化推遲到子類

在工廠方法模式中,主要涉及三個角色:抽象產品、具體產品、簡單工廠和具體工廠

抽象產品:抽象產品可以是一個接口或抽象類,定義了產品通用的方法,由具體子類來實現

具體產品:具體產品是抽象產品的實現類,它實現了抽象產品中定義的方法

抽象工廠:定義了創建產品的接口,包含一個或多個創建產品的抽象方法。

具體工廠:實現了抽象工廠接口,負責實例化具體產品。

(四)工廠方法模式應用

客戶在點披薩時,可以點不同口味的披薩,比如 北京的奶酪pizza、北京的胡椒 pizza 或者是倫敦的奶酪 pizza 、倫敦的胡椒 pizza
pizza類
//將Pizza 類做成抽象
public abstract class Pizza {protected String name; //名字//準備原材料, 不同的披薩不一樣,因此,我們做成抽象方法public abstract void prepare();public void bake() {System.out.println(name + " baking;");}public void cut() {System.out.println(name + " cutting;");}//打包public void box() {System.out.println(name + " boxing;");}public void setName(String name) {this.name = name;}
}

各種pizza

public class LDPepperPizza extends Pizza{@Overridepublic void prepare() {// TODO Auto-generated method stubsetName("倫敦的胡椒pizza");System.out.println(" 倫敦的胡椒pizza 準備原材料");}
}==============================================
public class LDCheesePizza extends Pizza{@Overridepublic void prepare() {// TODO Auto-generated method stubsetName("倫敦的奶酪pizza");System.out.println(" 倫敦的奶酪pizza 準備原材料");}
}==============================================
public class BJPepperPizza extends Pizza {@Overridepublic void prepare() {// TODO Auto-generated method stubsetName("北京的胡椒pizza");System.out.println(" 北京的胡椒pizza 準備原材料");}
}==============================================
public class BJCheesePizza extends Pizza {@Overridepublic void prepare() {// TODO Auto-generated method stubsetName("北京的奶酪pizza");System.out.println(" 北京的奶酪pizza 準備原材料");}}

orderpizza

public abstract class OrderPizza {//定義一個抽象方法,createPizza , 讓各個工廠子類自己實現abstract Pizza createPizza(String orderType);// 構造器public OrderPizza() {Pizza pizza = null;String orderType; // 訂購披薩的類型do {orderType = getType();pizza = createPizza(orderType); //抽象方法,由工廠子類完成//輸出pizza 制作過程pizza.prepare();pizza.bake();pizza.cut();pizza.box();} while (true);}// 寫一個方法,可以獲取客戶希望訂購的披薩種類private String getType() {try {BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));System.out.println("input pizza 種類:");String str = strin.readLine();return str;} catch (IOException e) {e.printStackTrace();return "";}}
}
public class LDOrderPizza extends OrderPizza {@OverridePizza createPizza(String orderType) {Pizza pizza = null;if(orderType.equals("cheese")) {pizza = new LDCheesePizza();} else if (orderType.equals("pepper")) {pizza = new LDPepperPizza();}// TODO Auto-generated method stubreturn pizza;}}==============================================
public class BJOrderPizza extends OrderPizza {@OverridePizza createPizza(String orderType) {Pizza pizza = null;if(orderType.equals("cheese")) {pizza = new BJCheesePizza();} else if (orderType.equals("pepper")) {pizza = new BJPepperPizza();}// TODO Auto-generated method stubreturn pizza;}}

PizzaStore?

public class PizzaStore {public static void main(String[] args) {String loc = "bj";if (loc.equals("bj")) {//創建北京口味的各種Pizzanew BJOrderPizza();} else {//創建倫敦口味的各種Pizzanew LDOrderPizza();}// TODO Auto-generated method stub}}

總結:當需要新增pizza類型時,只需要實現具體的產品和具體的工廠即可,而無需修改客戶端的代碼。

三、抽象工廠模式

(一)基本介紹

  1. 抽象工廠模式:定義了一個interface用于創建相關或有依賴關系的對象簇,而無需指明具體的類
  2. 抽象工廠模式可以將簡單工廠模式工廠方法模式進行整合。
  3. 從設計層面看,抽象工廠模式就是對簡單工廠模式的改進(或者稱為進一步的抽象)
  4. 將工廠抽象成兩層,AbsFactory(抽象工廠) 和 具體實現的工廠子類。程序員可以根據創建對象類型使用對應的工廠子類。這樣將單個的簡單工廠類變成了工廠簇,更利于代碼的維護和擴展。

?類圖如下:

(二)應用實例

抽象工廠

//一個抽象工廠模式的抽象層(接口)
public interface AbsFactory {//讓下面的工廠子類來 具體實現public Pizza createPizza(String orderType);
}

?工廠實現類

//這是工廠子類
public class BJFactory implements AbsFactory {@Overridepublic Pizza createPizza(String orderType) {System.out.println("~使用的是抽象工廠模式~");// TODO Auto-generated method stubPizza pizza = null;if(orderType.equals("cheese")) {pizza = new BJCheesePizza();} else if (orderType.equals("pepper")){pizza = new BJPepperPizza();}return pizza;}}==================================================
public class LDFactory implements AbsFactory {@Overridepublic Pizza createPizza(String orderType) {System.out.println("~使用的是抽象工廠模式~");Pizza pizza = null;if (orderType.equals("cheese")) {pizza = new LDCheesePizza();} else if (orderType.equals("pepper")) {pizza = new LDPepperPizza();}return pizza;}}

訂購披薩的類,通過聚合的方式設置工廠

public class OrderPizza {AbsFactory factory;// 構造器public OrderPizza(AbsFactory factory) {setFactory(factory);}private void setFactory(AbsFactory factory) {Pizza pizza = null;String orderType = ""; // 用戶輸入this.factory = factory;do {orderType = getType();// factory 可能是北京的工廠子類,也可能是倫敦的工廠子類pizza = factory.createPizza(orderType);if (pizza != null) { // 訂購okpizza.prepare();pizza.bake();pizza.cut();pizza.box();} else {System.out.println("訂購失敗");break;}} while (true);}// 寫一個方法,可以獲取客戶希望訂購的披薩種類private String getType() {try {BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));System.out.println("input pizza 種類:");String str = strin.readLine();return str;} catch (IOException e) {e.printStackTrace();return "";}}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/209177.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/209177.shtml
英文地址,請注明出處:http://en.pswp.cn/news/209177.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

RedisTemplate操作哈希數據

RedisTemplate操作哈希數據 概述常用方法添加哈希數據添加hashMap值判斷hashkey 獲取哈希數據獲取屬性值獲取hashMap值。獲取鍵值對。獲取map鍵是否有值判斷是否有map鍵。獲取鍵。獲取長度。集合方式獲取值。匹配獲取鍵值對 自增以double值大小自增。以long值大小自增。 修改刪…

IDEA中表明或者字段找不到時報紅

問題 idea 中mysql的sql語句報紅,無論表名還是表字段 原因 是由于sql方言導致的 當我們選擇某一個sql方言的時候,xml配置會按照指定規則校驗sql是否規范,并給出提示 解決方案 取消sql方言,設置sql方言為None。設置完重啟idea既…

CSS Grid布局入門:從零開始創建一個網格系統

CSS Grid布局入門:從零開始創建一個網格系統 引言 在響應式設計日益重要的今天,CSS Grid布局系統是前端開發中的一次革新。它使得創建復雜、靈活的布局變得簡單而直觀。本教程將通過分步驟的方式,讓你從零開始掌握CSS Grid,并在…

STM32上模擬CH340芯片的功能 (一)

#虛擬串口模擬CH340# 代碼gitee地址:STM32F103_CH340: 用STM32模擬ch340USB串口的功能 一、思路 1. 確定通信接口:CH340是一款USB轉串口芯片,因此您需要選擇STM32上的某個USB接口來實現USB通信。通常情況下,STM32系列芯片都有內…

Halcon聯合winform顯示以及處理

在窗口中添加窗體和按鈕,并在解決方案資源管理器中調加了導入Halcon導出的.cs文件,運行出現下圖的問題: 問題1:CS0017 程序定義了多個入口點。使用/main(指定包含入口點的類型)進行編譯。 解決方案1.: 右…

SAP UI5 walkthrough step3 Controls

在上一步&#xff0c;我們是直接用index.html 中的body 里面的DIVision去輸出 hello world&#xff0c; 在這個章節&#xff0c;我們將用SAP UI5 的標準控件 sap/m/Text 首先&#xff0c;我們去修改 webapp/index.html <!DOCTYPE html> <html> <head><…

jenkins搭建文檔

jenkins搭建文檔 簡介一、安裝運行環境1、安裝JDK環境1&#xff09;查詢自帶的JDK2&#xff09;卸載自帶的JDK3&#xff09;創建java文件夾并將jdk上傳到該文件夾4&#xff09;解壓5&#xff09;配置環境變量6&#xff09;配置生效7&#xff09;驗證是否成功 2、安裝maven環境1…

哪些設備可以隔離沖突域哪些可以隔離廣播域,哪些設備什么都無法隔離

在計算機網絡中&#xff0c;有兩個概念與網絡隔離相關&#xff1a;沖突域和廣播域。沖突域表示一個物理網絡中共享相同帶寬的設備集合&#xff0c;而廣播域是指網絡中一個廣播消息&#xff08;如ARP請求&#xff09;傳播的范圍。以下是一些設備和技術&#xff0c;它們對沖突域和…

使用Docker在Debian上構建GRBL模擬器鏡像:簡明步驟和操作指南

概述編譯編寫 Dockerfile構建鏡像運行測試其他 概述 本文將詳細介紹如何在Debian系統上通過Docker構建GRBL模擬器鏡像&#xff0c;以便進行數控機床的仿真測試。GRBL是一種開源的控制系統&#xff0c;用于控制三軸CNC機床、激光雕刻、激光切割&#xff0c;而在Docker容器中運…

DouyinAPI接口開發系列丨商品詳情數據丨視頻詳情數據

電商API就是各大電商平臺提供給開發者訪問平臺數據的接口。目前&#xff0c;主流電商平臺如淘寶、天貓、京東、蘇寧等都有自己的API。 二、電商API的應用價值 1.直接對接原始數據源&#xff0c;數據提取更加準確和完整。 2.查詢速度更快&#xff0c;可以快速響應用戶請求實現…

nodejs發起http或https請求

前言&#xff1a;使用node內置模塊http、https http請求 const express require(express) const http require(http)const app express()const loginConfig (token) > {return {hostname: api.test.com,port: 80,path: /test?access_token${token},method: GET} }app.…

LeetCode968. Binary Tree Cameras

文章目錄 一、題目二、題解 一、題目 You are given the root of a binary tree. We install cameras on the tree nodes where each camera at a node can monitor its parent, itself, and its immediate children. Return the minimum number of cameras needed to monito…

Kubernetes(K8s)數據存儲-09

數據存儲 在前面已經提到&#xff0c;容器的生命周期可能很短&#xff0c;會被頻繁地創建和銷毀。那么容器在銷毀時&#xff0c;保存在容器中的數據也會被清除。這種結果對用戶來說&#xff0c;在某些情況下是不樂意看到的。為了持久化保存容器的數據&#xff0c;kubernetes引…

【圖像拼接】論文精讀:Rectangling panoramic images via warping

第一次來請先看這篇文章:【圖像拼接(Image Stitching)】關于【圖像拼接論文精讀】專欄的相關說明,包含專欄使用說明、創新思路分享等(不定期更新) 圖像拼接系列相關論文精讀 Seam Carving for Content-Aware Image ResizingAs-Rigid-As-Possible Shape ManipulationAdap…

Qt基礎-組件的添加、刪除或更新

本文介紹如何在Qt中組件的添加、刪除或更新。 概述 有時安裝完qt后發現當前的組件需要進一步調整,這時就需要進一步操作安裝的文件。 QT的組件管理軟件并沒有在開始菜單或者桌面添加快捷方式(5.9版本),也沒有在代碼編輯界面設置相關的選項,藏的比較深。 操作步驟 找到…

vue使用甘特圖dhtmlxgantt + gantt.addTaskLayer

效果圖&#xff1a; 甘特圖 官網地址 gantt安裝與使用 vue版---部分功能收費 安裝gantt 或 引入文件 npm install dhtmlx-gantt -save或import gantt from "/public/static/dhtmlxgantt/dhtmlxgantt.js"; import "/public/static/dhtmlxgantt/locale/local…

校驗數據是否重疊(各種操作符>,<,>=,<=,or,and)

最近接到一個需求&#xff0c;其中部分功能涉及到數據的重疊校驗&#xff0c;并且錄入的數據需要包含各種操作符。如果只通過java代碼來查詢并進行循環判斷的話&#xff0c;判斷情況會很復雜&#xff0c;幸好有同事的幫忙提供了一個用sql查詢重疊部分的方法&#xff0c;現在分享…

如何給Linux硬盤分區?

在Windows操作系統中&#xff0c;磁盤分區是將物理地址分開&#xff0c;再在分區上建立目錄。Linux正好相反&#xff0c;是先有目錄&#xff0c;再將物理地址映射到目錄中。在Linux操作系統中&#xff0c;所有路徑都是從根目錄開始的。那么如何給Linux硬盤分區呢&#xff1f; L…

Python列表list數組array用法實例解析

Python列表(list)/數組(array)用法實例解析 在Python中&#xff0c;列表(List)和數組(Array)都是常用的數據類型&#xff0c;它們都可以用于存儲多個元素。本文將詳細講解Python中列表(List)和數組(Array)的使用方法&#xff0c;包括創建、訪問、添加、刪除等操作。 創建列表…