【設計模式深度剖析】【2】【創建型】【工廠方法模式】

👈?上一篇:單例模式 ? ?|?? 下一篇:抽象工廠模式👉?

目錄

  • 工廠方法模式
    • 概覽
    • 工廠方法模式的定義
      • 英文原話
      • 直譯
    • 工廠方法模式的4個角色
      • 抽象工廠(Creator)角色
      • 具體工廠(Concrete Creator)角色
      • 抽象產品(Product)角色
      • 具體產品(Concrete Product)角色
      • 類圖
      • 代碼示例
        • 抽象工廠Creator.java
        • 具體工廠ConcreteCreator.java
        • 抽象產品Product.java
        • 具體產品ConcreteProduct.java
        • 應用代碼ClientFactoryMethodDemo.java
    • 工廠方法模式的應用
      • 工廠方法模式的優點
      • 工廠方法模式的使用場景
    • 工廠方法模式的示例解析
      • 類圖
      • 1. 抽象工廠類:FruitGardener.java(果子園接口,生產各類水果的)
      • 2. 具體工廠類:
        • 2.1 具體的某果園:AppleGardener.java (蘋果園類,生產蘋果)
        • 2.2 具體的某果園:GrapeGardener.java(葡萄園類,生產葡萄)
      • 3. 抽象產品類:Fruit.java(水果接口,抽象的水果類)
      • 4. 具體產品類:
        • 4.1 具體的某類水果:Apple.java(蘋果類,是一種具體的水果)
        • 4.2 具體的某類水果:Grape.java(葡萄類,是一種具體的水果)
      • 5. 測試類

工廠方法模式

工廠方法模式(Factory Method Pattern)又叫虛擬構造函數(Virtual Constructor)模式
或者多態性工廠(PolymorphicFactory)模式
。工廠方法模式的用意是定義一個創建產品對象
的工廠接口,將實際創建性工作推遲到子類中

工廠模式可分為簡單工廠、工廠方法和抽象工廠模式。

  • 簡單工廠模式中一個工廠類處于對產品類實例化的中心位置上,它知道每一個產品,它決定哪一個產品類應當被實例化

這個模式的優點是允許客戶端相對獨立于產品創建的過程,并且在系統引入新產品的時候無須修改客戶端,即在某種程度上支持“開-閉”原則(一個軟件實體應當對擴展開放,對修改關閉)。
這個模式的缺點是對 “開-閉” 原則的支持不夠,因為如果有新的產品加入到系統中,則需要修改工廠類,將必要的邏輯加入到工廠類中。

  • 工廠方法模式簡單工廠模式的進一步抽象和推廣。由于使用了多態性,工廠方法模式保持了簡單工廠模式的優點,且克服了它的缺點。

首先,在工廠方法模式中,核心的工廠類不再負責所有產品的創建,而是將具體創建的工作交給子類去做。這個核心類則成為一個抽象工廠角色,僅負責給出具體工廠子類必須實現的接口,而不接觸哪個產品類應當被實例化的細節。此種進一步抽象化的結果,使這種工廠方法模式可以用來允許系統在不修改具體工廠角色的情況下引進新的產品,這一特點使得工廠模式具有超過簡單工廠的優越性。

  • 抽象工廠模式是所有形態的工廠模式中最為抽象和最具有一般性的一種形態

    抽象工廠模式與工廠方法模式的最大區別就在于,工廠方法模式針對的是一個產品等級結構;而抽象工廠模式則需要面對多個產品等級結構

概覽

  • 工廠方法模式的定義

  • 工廠方法模式的4個角色

  • 工廠方法模式的應用

    • 工廠方法模式的優點
    • 工廠方法模式的使用場景
  • 工廠方法模式的示例解析

  • 待辦:工廠方法模式的使用場景 第三條/第四條

工廠方法模式的定義

英文原話

Define an interface for creating an object, but let subclasses decide which class to instantiate. FactoryMethod lets a class defer instantiation to subclasses.

直譯

意思是:定義一個用于創建對象的接口,讓子類決定實例化哪個類。工廠方法使一個類的實例化延遲到其子類。

工廠方法模式的4個角色

抽象工廠(Creator)角色

該角色是工廠方法模式的核心,與應用系統無關,任何在創建對象的工廠類必須實現這個接口。

具體工廠(Concrete Creator)角色

該角色實現了抽象工廠接口,含有與應用密切相關的邏輯,并且受到應用程序的調用以創建產品對象。

抽象產品(Product)角色

該角色負責定義產品的共性,實現對產品最抽象的定義。

具體產品(Concrete Product)角色

該角色實現抽象產品角色所聲明的接口,工廠方法模式所創建的每一個對象都是某個具體產品角色的實例。

類圖

工廠方法模式類圖

代碼示例

示例代碼

抽象工廠Creator.java
public interface Creator {//工廠方法//創建一個產品對象,其輸入參數類型可自行設置public <T extends Product> T factory(Class<T> c);
}
具體工廠ConcreteCreator.java
public class ConcreteCreator implements Creator {@Overridepublic <T extends Product> T factory(Class<T> c) {Product product = null;try {product= (Product) Class.forName(c.getName()).newInstance();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return (T) product;}
}
抽象產品Product.java
public interface Product {//產品類的公共方法public void method1();public void method2();
}
具體產品ConcreteProduct.java
public class ConcreteProduct implements Product {@Overridepublic void method1() {//業務邏輯處理代碼System.out.println("test method1()");}@Overridepublic void method2() {//業務邏輯處理代碼}
}
應用代碼ClientFactoryMethodDemo.java
public class ClientFactoryMethodDemo {public static void main(String[] args) {Creator creator = new ConcreteCreator();Product product = creator.factory(ConcreteProduct.class);//繼續業務處理product.method1();}
}

[注]:上述通用代碼是一個比較實用的、易擴展的框架,可以根據實際項目需要進行擴展應用。

工廠方法模式的應用

工廠方法模式的優點

  1. 良好的封裝性,代碼結構清晰。一個對象創建是有條件約束的,如果一個調用者需要一個具體的產品對象
    只要知道這個產品的類名或約束字符串即可,不用知道創建對象的過程如何,降低了模塊間的耦合。
  2. 優秀的可擴展性在增加產品類的情況下,只要適當地修改具體的工廠類或擴展一個工廠類,就可以適應變化
  3. 屏蔽產品類。產品類的實現如何變化,調用者都不需要關心,而只需要關心產品的接口,只要接口保持不變,
    系統的上層模塊就不需要發生變化
    。因為產品的實例化是由工廠類負責的,具體生產何種產品對象是由不同的工廠類
    決定的。
  4. 工廠方法模式是典型的解耦框架高層模塊只需要知道產品的抽象類,其他的實現類都不用關心。
    工廠方法模式符合迪米特法則 (又叫最少知識原則(Least Knowledge Principle,LKP).
    只與你直接的朋友們通信(Only talk to your immediatefriends);
    不要跟“陌生人”說話(Don’t talk to strangers);),也符合依賴倒置原則
    (高層模塊不應該依賴低層模塊,兩者都依賴其抽象;抽象不依賴細節 細節應該依賴于抽象。),只依賴產品類的抽象;
    另外還符合里氏替換原則,可以使用產品子類替換產品父類。

工廠方法模式的使用場景

工廠方法模式在項目中使用得非常頻繁,在很多框架的代碼中都可以發現工廠方法模式的應用。可使用工廠方法模式的典型場景如下。

  • 工廠方法模式是new一個對象的替代品,因此在所有需要生成對象的地方都可以使用,
    但是需要慎重考慮是否需要增加一個工廠類進行管理,增加代碼的復雜度。
  • 需要靈活的、可擴展的框架時,可以考慮采用工廠方法模式。
  • 工廠方法模式可以用在異構項目中,例如,通過WebService與一個非Java的項目交互,雖然WebService號稱是可以做到異構系統的同構化,但是在實際開發中,還是會碰到很多問題,如類型問題、WSDL文件的支持問題等。從WSDL中產生的對象都認為是一個產品,然后由一個具體的工廠類進行管理,減少與外圍的耦合。
  • 工廠方法模式可以使用在測試驅動開發的框架下。例如,測試一個類 A,就需要將與類A關聯的類B也同時產生出來,使用工廠方法模式可以將類B虛擬出來,避免類A與類B的耦合。
  • [注]工廠方法模式還可以與其他模式混合使用(如模板方法模式、單例模式、原型模式等),從而構造出擴展性更好的設計。

工廠方法模式的示例解析

代碼示例

通過農場系統演示工廠方法模式的應用(但是工廠方法模式只能針對一個產品等級結構如A產品B產品。但是如果是A產品與B產品的第一等級第二等級,這種情況要抽象工廠模式。)

類圖

FuitProductFactory.png

1. 抽象工廠類:FruitGardener.java(果子園接口,生產各類水果的)

package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 水果園丁FruitGardener接口是抽象工廠** @author Polaris 2024/5/16*/
public interface FruitGardener {Fruit factory();
}

2. 具體工廠類:

2.1 具體的某果園:AppleGardener.java (蘋果園類,生產蘋果)

該具體工廠-蘋果園工廠,封裝了實例化具體產品-蘋果對象的過程

package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 蘋果園丁AppleGardener實現FruitGardener接口,是一個用于生產蘋果的具體工廠** @author Polaris 2024/5/16*/
public class AppleGardener implements FruitGardener {@Overridepublic Fruit factory() {return new Apple();}
}
2.2 具體的某果園:GrapeGardener.java(葡萄園類,生產葡萄)

該具體工廠-葡萄園工廠,封裝了實例化具體產品-葡萄對象的過程

package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 葡萄園丁GrapeGardener實現FruitGardener接口,是一個用于生產葡萄的具體工廠** @author Polaris 2024/5/16*/
public class GrapeGardener implements FruitGardener {@Overridepublic Fruit factory() {return new Grape();}
}

3. 抽象產品類:Fruit.java(水果接口,抽象的水果類)

package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 水果Fruit接口是抽象產品** @author Polaris 2024/5/16*/
public interface Fruit {//生長void grow();//收獲void harvest();//栽種void plant();
}

4. 具體產品類:

4.1 具體的某類水果:Apple.java(蘋果類,是一種具體的水果)

由于蘋果是一類具體的水果類,因此它對抽象的水果類進行了實現,當然同時它也有獨自屬于它自己的方法。

package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 蘋果Apple實現Fruit接口,是一個具體產品** @author Polaris 2024/5/16*/
public class Apple implements Fruit {private int treeAge;public int getTreeAge() {return treeAge;}public void setTreeAge(int treeAge) {this.treeAge = treeAge;}@Overridepublic void grow() {System.out.println("蘋果樹在生長");}@Overridepublic void harvest() {System.out.println("收獲蘋果");}@Overridepublic void plant() {System.out.println("栽種蘋果");}
}
4.2 具體的某類水果:Grape.java(葡萄類,是一種具體的水果)

由于葡萄是一類具體的水果類,因此它對抽象的水果類進行了實現,當然同時它也有獨自屬于它自己的方法。

package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 葡萄Grape實現Fruit接口,是一個具體產品** @author Polaris 2024/5/16*/
public class Grape implements Fruit {private boolean seedless;public boolean isSeedless(){return seedless;}public void setSeedless(boolean seedless){this.seedless=seedless;}@Overridepublic void grow() {System.out.println("葡萄正在生長...");}@Overridepublic void harvest() {System.out.println("收獲葡萄");}@Overridepublic void plant() {System.out.println("栽種葡萄");}
}

5. 測試類

具體某類水果工廠來生產對應的某水果對象,

該水果對象是某具體水果類的實例,

而該具體水果實例實現了抽象的水果類,

里氏替換原則,父類的引用可以指向子類實例,因為子類類型一定是父類類型(或者實現的接口的類型)

package com.polaris.designpattern.list1.creational.pattern2.factorymethod;/*** 下面是一個應用場景代碼** @author Polaris 2024/5/16*/
public class ClientDemo {public static void main(String[] args) {//蘋果園丁工廠FruitGardener fruitGardener = new AppleGardener();//通過工廠生產蘋果Fruit apple = fruitGardener.factory();apple.plant();apple.grow();apple.harvest();fruitGardener = new GrapeGardener();//通過工廠生產葡萄Fruit grape = fruitGardener.factory();grape.plant();grape.grow();grape.harvest();}
}

👈?上一篇:單例模式 ? ?|?? 下一篇:抽象工廠模式👉?

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

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

相關文章

關于光照模型

關于光照模型 早期學習筆記&#xff0c;轉載自早期Excel。 存在大量格式錯誤、可讀性非常低&#xff0c;建議等待作者修復后閱讀、或者作為查找性材料使用。 中文名英文名/縮寫說明長什么樣蘭伯特光照模型Lambert Lighting1.蘭伯特反射(Lambert)是最常見的一種漫反射&#x…

iptables防火墻【其二 實驗篇】

保存&#xff0c;還原規則 防火墻規則的備份和還原 導出&#xff08;備份&#xff09;所有表的規則 iptables-save > /opt/ipt.txt 導入&#xff08;還原&#xff09;規則 iptables-restore < /opt/ipt.txt 將iptables規則文件保存在 /etc/sysconfig/iptables 中&#xf…

亞馬遜賣家賬號注冊復雜嗎?需要什么輔助工具嗎?

在當今數字化的商業世界中&#xff0c;亞馬遜作為全球最大的電商平臺之一&#xff0c;吸引著無數的賣家和買家。對于想要進入亞馬遜銷售市場的賣家來說&#xff0c;首先要完成的一項重要任務就是注冊亞馬遜賣家賬號。本文將詳細介紹亞馬遜注冊的步驟、所需時間&#xff0c;以及…

LIMS系統能解決實驗室管理的哪些痛點

LIMS&#xff08;Laboratory Information Management System&#xff0c;實驗室信息管理系統&#xff09;在解決實驗室管理的痛點方面發揮著重要作用。以下是LIMS系統能夠解決的一些主要痛點&#xff1a; 一、人工介入大量重復性工作 LIMS系統能夠自動化處理實驗室中的許多重復…

[深度學習]基于yolov8+bytetrack+pyqt5實現車輛進出流量統計+車輛實時測速實現

以前使用過yolov5deepsort實現過車輛進出流量統計車輛實時測速&#xff0c;可以看我往期視頻&#xff0c;這回改成yolov8bytetrack實現&#xff0c;實時性更好&#xff0c;原理和原來一樣。車流量進出統計車速測量優點&#xff1a; 使用目標檢測算法考慮bbox抖動&#xff0c;解…

C-數據結構-單向鏈表(帶頭節點)

單向鏈表帶頭節點&#xff08;head&#xff09;&#xff08;數據域&#xff0c;指針域&#xff09; 隨機訪問性比較差 但是插入刪除操作較為簡單。 list.h #ifndef LIST_H__ #define LIST_H__typedef int datatype;typedef struct node_st {datatype data;struct node_st *ne…

將富文本編輯器中的H標簽處理成樹形結構,支持無限層級

做富文本編輯器時&#xff0c;需要將文本里的標題整理成樹形數據&#xff0c; // 這里是數據結構 const data [{"id": "hkyrq2ndc-36yttda0lme00","text": "阿薩德阿薩德阿薩","level": 1,"depth": 1,},{"…

Window Linux 權限提升

#基礎點&#xff1a; 0、為什么我們要學習權限提升轉移技術&#xff1a; 簡單來說就是達到目的過程中需要用到它 心里要想著我是誰 我在哪 我要去哪里 1、具體有哪些權限需要我們了解掌握的&#xff1a; 后臺權限&#xff0c;數據庫權限&#xff0c;Web權限&#xff0c;用戶權…

【VTKExamples::Texture】第六期 TextureThreshold

很高興在雪易的CSDN遇見你 VTK技術愛好者 QQ:870202403 公眾號:VTK忠粉 前言 本文分享VTK樣例TextureThreshold,并解析接口vtkTexture,希望對各位小伙伴有所幫助! 感謝各位小伙伴的點贊+關注,小易會繼續努力分享,一起進步! 你的點贊就是我的動力(^U^)ノ~Y…

127.數據異構方案

文章目錄 前言一、數據異構的常用方法1. 完整克隆2. MQ方式3. binlog方式 二、MQ與Binlog方案實現MQ方式binlog方式注意點 三、總結 前言 何謂數據異構&#xff1a;把數據按需&#xff08;數據結構、存取方式、存取形式&#xff09;異地構建存儲。比如我們將DB里面的數據持久化…

Android 安全補丁介紹

Android 安全補丁介紹 每月安全補丁更新&#xff1a;https://source.android.com/docs/security/bulletin CEV 全稱&#xff1a; Common Vulnerabilities and Exposures (CVE) 常見漏洞和暴露 (CVE) 安全補丁版本查看&#xff1a;設置&#xff0c;關于手機&#xff0c;Andro…

前端基礎入門三大核心之HTML篇:無序列表的深度探索

前端基礎入門三大核心之HTML篇&#xff1a;無序列表的深度探索 一、無序列表基礎概念與作用1.1 什么是無序列表&#xff1f;1.2 無序列表的作用 二、基本用法與代碼示例2.1 最簡單的無序列表2.2 添加自定義樣式 三、進階應用與技巧3.1 列表嵌套3.2 利用CSS實現復雜布局3.3 安全…

云和恩墨海外首秀在吉隆坡召開的2024中國智能科技與文化展覽會

作為中馬建交50周年官方重點推薦的活動之一&#xff0c;2024中國智能科技與文化展覽會&#xff08;第四屆&#xff09;于5月20至21日在毗鄰吉隆坡雙子塔的吉隆坡國際會展中心舉辦。本次展覽會獲得馬來西亞科學技術創新部、馬來西亞通訊部、中國駐馬來西亞大使館和馬來西亞中華總…

【Linux學習】進程地址空間與寫時拷貝

文章目錄 Linux進程內存布局圖&#xff1a;內存布局的驗證 進程地址空間寫時拷貝 Linux進程內存布局圖&#xff1a; 地址空間的范圍&#xff0c;在32位機器上是2^32比特位,也就是[0,4G]。 內存布局的驗證 代碼驗證內存布局&#xff1a; 驗證代碼&#xff1a; #include<s…

linux系統安全加固

目錄 1、賬戶安全基本措施 1&#xff09;系統賬戶清理 2&#xff09;密碼安全控制 3&#xff09;命令歷史限制 2、用戶切換及提權 1&#xff09;使用 su命令切換用戶 2&#xff09;使用sudo機制提升權限 3、系統引導和安全登錄控制 1&#xff09;開機安全控制 2&…

頭歌實踐教學平臺:Junit實訓入門篇

第2關&#xff1a;Junit注解 任務描述 給出一個帶有注解的Junit代碼及其代碼打印輸出&#xff0c;要求學員修改注解位置&#xff0c;讓輸出結果變為逆序。 相關知識 Junit注解 Java注解&#xff08;(Annotation&#xff09;的使用方法是" 注解名" 。借助注解&a…

python數據處理與分析入門-Pandas數據可視化例子

相關內容 Matplotlib可視化練習 Pandas 數據可視化總結 柱狀圖 reviews[points].value_counts().sort_index().plot.bar()散點圖 reviews[reviews[price] < 100].sample(100).plot.scatter(xprice, ypoints)蜂窩圖 reviews[reviews[price] < 100].plot.hexbin(xprice…

Helm安裝kafka3.7.0無持久化(KRaft 模式集群)

文章目錄 2.1 Chart包方式安裝kafka集群 5.開始安裝2.2 命令行方式安裝kafka集群 搭建 Kafka-UI三、kafka集群測試3.1 方式一3.2 方式二 四、kafka集群擴容4.1 方式一4.2 方式二 五、kafka集群刪除 參考文檔 [Helm實踐---安裝kafka集群 - 知乎 (zhihu.com)](https://zhuanlan.…

virtualbox共享文件夾沒有訪問權限

設置好共享文件夾之后&#xff0c;進入虛擬機&#xff0c;共享文件夾的地址是/media/sf_shared。 想要使用cd命令進入該文件夾時&#xff0c;你可能會發現此文件夾無法訪問&#xff0c;系統提示的原因是權限不足。 在虛擬機下查看共享文件夾的屬性&#xff0c;發現該目錄的所…

Nginx - 健康檢查終極指南:探索Upstream Check模塊

文章目錄 概述upstream_check_module模塊安裝和配置指南模塊安裝步驟基本配置示例詳細配置說明檢查類型和參數常見問題及解決方案 SSL檢查和DNS解析功能SSL檢查配置示例和說明配置示例 DNS解析配置示例和說明配置示例 結合實際應用場景的高級配置示例綜合SSL檢查與DNS解析 總結…