工廠模式總結——三個工廠

来源:https://www.cnblogs.com/xiaobaiLX/archive/2022/09/24/16725442.html
-Advertisement-
Play Games

在創建型模式中,工廠模式是我們日常使用最為頻繁的設計模式之一。工廠模式可細分為簡單工廠模式、工廠方法模式、抽象工廠模式。 簡單工廠模式 模式簡介 簡單工廠模式:根據參數返回不同類的實例,這些類通常具有共同的父類。 簡單工廠模式包括三個角色: 工廠 (Factory):用於創建所需產品,提供靜態工廠方 ...


在創建型模式中,工廠模式是我們日常使用最為頻繁的設計模式之一。工廠模式可細分為簡單工廠模式、工廠方法模式、抽象工廠模式。

簡單工廠模式

模式簡介

簡單工廠模式:根據參數返回不同類的實例,這些類通常具有共同的父類。

簡單工廠模式包括三個角色:

  1. 工廠 (Factory):用於創建所需產品,提供靜態工廠方法,返回抽象產品類型 Product;
  2. 抽象產品 (Product):是工廠創建的所有對象的父類,封裝了各種共有方法;
  3. 具體產品 (ConcreateProduct):工廠創建目標,繼承抽象產品,實現了抽象產品的抽象方法。

應用實例

image-20220911203830271

  1. 工廠——FruitFactory

    public class FruitFactory {
    
        public static Object createFruit(String clazzName)  throws Exception{
            Object obj = null;
            if (clazzName.equals(Apple.class.getName())){
                obj = new Apple();
            } else if (clazzName.equals(Strawberry.class.getName())){
                obj = new Strawberry();
            } else if (clazzName.equals(Banana.class.getName())){
                obj = new Banana();
            } else {
                throw new ClassNotFoundException("沒有找到該類");
            }
            return obj;
        }
    
        //升級簡化版
        /*public static Object create(String clazzName) throws Exception{
            Object obj = null;
            Class clazz = Class.forName(clazzName);
            if (clazz.isAssignableFrom(Fruit.class)){
                obj = clazz.newInstance();
            } else {
                throw new ClassNotFoundException("沒有找到該類");
            }
            return obj;
        }*/
    }
    
  2. 抽象產品——Fruit

    public abstract class Fruit {
        public abstract void getInfo();
    }
    
  3. 具體產品——Apple、Banana、Strawberry

    • Apple
    public class Apple extends Fruit{
        @Override
        public void getInfo() {
            System.out.println("這是一個砸中牛頓腦袋的蘋果");
        }
    }
    
    • Banana
    public class Banana extends Fruit{
        @Override
        public void getInfo() {
            System.out.println("這是一根讓猶太人致富的香蕉");
        }
    }
    
    • Strawberry
    public class Strawberry extends Fruit{
        @Override
        public void getInfo() {
            System.out.println("這是一顆甜到你心裡的草莓");
        }
    }
    
  4. 客戶端

    public class MainTest {
        public static void main(String[] args) throws Exception {
            //要個蘋果
            Apple apple = (Apple) FruitFactory.createFruit(Apple.class.getName());
            apple.getInfo();
            //要顆草莓
            Strawberry strawberry = (Strawberry) FruitFactory.createFruit(Strawberry.class.getName());
            strawberry.getInfo();
            //要根香蕉
            Banana banana = (Banana) FruitFactory.createFruit(Banana.class.getName());
            banana.getInfo();
        }
    }
    

模式總結

優點:實現簡單,屏蔽了對象創建過程,實現了對象創建和使用的分離。

缺點:集中了所有產品創建邏輯,職責過重;擴展困難,一旦添加類需修改源碼;使用靜態工廠方法,工廠角色無法形成繼承結構。

使用場景:工廠負責創建對象較少。

工廠方法模式

模式簡介

工廠方法模式:定義了一個用於創建對象的介面,但是讓子類決定將哪個類實例化。工廠方法讓一個類的實例化延遲到了子類。

工廠方法模式在簡單工廠模式的基礎上,引入了抽象工廠,將具體產品的創建延遲到了具體工廠,剋服了簡單工廠模式職責過重的缺點。

工廠方法模式包括了 4 個角色:

  1. 抽象工廠(AbstractFactory):定義了抽象工廠方法,用於返回一個產品,具體返回哪類產品由具體工廠決定。
  2. 抽象產品(AbstractProduct):是所有具體產品的公共父類,定義了產品的介面。
  3. 具體工廠(ConcreteFactory):是抽象工廠的子類,實現了抽象工廠的工廠方法,返回一個具體產品。
  4. 具體產品(ConcreteProduct):實現了抽象產品介面,由具體工廠創建。

應用實例

image-20220911203219104

  1. 抽象工廠——FruitFactory

    public abstract class FruitFactory {
        public abstract Fruit createFruit();
    }
    
  2. 抽象產品——Fruit

    public abstract class Fruit {
        public abstract void getInfo();
    }
    
  3. 具體工廠——AppleFactory、BananaFactory、StrawberryFactory

    • AppleFactory
    public class AppleFactory extends FruitFactory{
    
        @Override
        public Fruit createFruit() {
            return new Apple();
        }
    }
    
    • BananaFactory
    public class BananaFactory extends FruitFactory{
    
        @Override
        public Fruit createFruit() {
            return new Banana();
        }
    }
    
    • StrawberryFactory
    public class StrawberryFactory extends FruitFactory{
    
        @Override
        public Fruit createFruit() {
            return new Strawberry();
        }
    }
    
  4. 具體產品——Apple、Banana、Strawberry

    • Apple
    public class Apple extends Fruit {
        @Override
        public void getInfo() {
            System.out.println("這是一個砸中牛頓腦袋的蘋果");
        }
    }
    
    • Banana
    public class Banana extends Fruit {
        @Override
        public void getInfo() {
            System.out.println("這是一根讓猶太人致富的香蕉");
        }
    }
    
    • Strawberry
    public class Strawberry extends Fruit {
        @Override
        public void getInfo() {
            System.out.println("這是一顆甜到你心裡的草莓");
        }
    }
    
  5. 客戶端

    public class MainTest {
        public static void main(String[] args) throws Exception {
            FruitFactory factory = null;
            //要個蘋果
            factory = new AppleFactory();
            Fruit apple = factory.createFruit();
            apple.getInfo();
            //要顆草莓
            factory = new StrawberryFactory();
            Fruit strawberry = factory.createFruit();
            strawberry.getInfo();
            //要根香蕉
            factory = new BananaFactory();
            Fruit banana = factory.createFruit();
            banana.getInfo();
        }
    }
    

模式總結

優點

  1. 隱藏了對象創建細節,用戶創建對象時無需知道具體類名,只需知道相應的工廠類即可創建相應類對象。
  2. 在系統中添加新的產品時不會對現有代碼產生影響,具有良好的擴展性,符合開閉原則。

缺點

  1. 每個產品需要添加對應的具體工廠類,類的數量因此成對增加,增加了系統複雜性和性能消耗。
  2. 引入了抽象層,增加了系統的抽象性和理解難度。

使用場景

  1. 客戶端不需要知道它所需創建的類對象的類名;
  2. 抽象類通過子類來指定創建具體哪個類的對象。

抽象工廠模式

模式簡介

抽象工廠:提供一個創建一系列相關或相關以來對象的介面,從而無需指定他們具體的類。

兩個概念

產品等級結構:即產品的繼承結構,水果是個抽象類,其子類包括蘋果、香蕉、草莓,則抽象類與具體類之間構成了一個產品等級結構。

產品族:在抽象工廠模式中,產品族是同一個工廠生產的不同產品等級結構中的一組產品。例如當前有兩個生產水果的工廠A和B都生產水果蘋果、香蕉、草莓,則工廠A生產的蘋果、香蕉、草莓構成一個產品族。

抽象工廠模式與工廠方法模式的區別在於,工廠方法模式針對的是一個產品等級結構,每一個具體工廠只能創建一個產品;而抽象工廠模式針對的是多個產品等級結構,其每個具體工廠負責創建一族的產品。

抽象工廠模式包括了 4 個角色:

  1. 抽象工廠(AbstractFactory):聲明瞭一組用於創建一族產品的方法,每個方法對應一種產品。
  2. 抽象產品(AbstractProduct):為每種產品聲明介面,在抽象產品中聲明瞭產品所具有的業務方法。
  3. 具體工廠(ConcreteFactory):實現了抽象工廠中聲明的創建產品的方法,生成了一組具體產品,這些具體產品構成了一個產品族,每個產品位於某個產品等級結構中。
  4. 具體產品(ConcreteProduct):實現了抽象產品介面,由具體工廠創建。

應用實例

image-20220911202602724

  1. 抽象工廠——FruitFactory

    public abstract class FruitFactory {
    
        public abstract Fruit createApple();
    
        public abstract Fruit createBanana();
    
        public abstract Fruit createStrawberry();
    
    }
    
  2. 抽象產品

    public abstract class Fruit {
        public abstract void getInfo();
    }
    
  3. 具體工廠——FruitFactoryA、FruitFactoryB

    • FruitFactoryA
    public class FruitFactoryA extends FruitFactory {
        
        @Override
        public Fruit createApple() {
            return new AppleA();
        }
    
        @Override
        public Fruit createBanana() {
            return new BananaA();
        }
    
        @Override
        public Fruit createStrawberry() {
            return new StrawberryA();
        }
    }
    
    • FruitFactoryB
    public class FruitFactoryB extends FruitFactory {
    
        @Override
        public Fruit createApple() {
            return new AppleB();
        }
    
        @Override
        public Fruit createBanana() {
            return new BananaB();
        }
    
        @Override
        public Fruit createStrawberry() {
            return new StrawberryB();
        }
    }
    
  4. 具體產品AppleA、AppleB、BananaA、BananaB、StrawberryA、StrawberryB

    • AppleA
    public class AppleA extends Fruit {
        @Override
        public void getInfo() {
            System.out.println("這是一個砸中牛頓腦袋的蘋果,由工廠A生產");
        }
    }
    
    • AppleB
    public class AppleB extends Fruit {
        @Override
        public void getInfo() {
            System.out.println("這是一個砸中牛頓腦袋的蘋果,由工廠B生產");
        }
    }
    
    • BananaA
    public class BananaA extends Fruit {
        @Override
        public void getInfo() {
            System.out.println("這是一根讓猶太人致富的香蕉,由工廠A生產");
        }
    }
    
    • BananaB
    public class BananaB extends Fruit {
        @Override
        public void getInfo() {
            System.out.println("這是一根讓猶太人致富的香蕉,由工廠B生產");
        }
    }
    
    • StrawberryA
    public class StrawberryA extends Fruit {
        @Override
        public void getInfo() {
            System.out.println("這是一顆甜到你心裡的草莓,由工廠A生產");
        }
    }
    
    • StrawberryB
    public class StrawberryB extends Fruit {
        @Override
        public void getInfo() {
            System.out.println("這是一顆甜到你心裡的草莓,由工廠B生產");
        }
    }
    
  5. 客戶端

    public class MainTest {
        public static void main(String[] args) throws Exception {
            FruitFactory factoryA = new FruitFactoryA();
            FruitFactory factoryB = new FruitFactoryA();
            //要個蘋果
            Fruit appleA = factoryA.createApple();
            appleA.getInfo();
            Fruit appleB = factoryB.createApple();
            appleB.getInfo();
            //要顆草莓
            Fruit strawberryA = factoryA.createStrawberry();
            strawberryA.getInfo();
            Fruit strawberryB = factoryA.createStrawberry();
            strawberryB.getInfo();
            //要根香蕉
            Fruit bananaA = factoryA.createStrawberry();
            bananaA.getInfo();
            Fruit bananaB = factoryA.createStrawberry();
            bananaB.getInfo();
        }
    }
    

模式總結

優點

  1. 隔離了具體類的生成,更換一個具體工廠就可以在某種程度上改變整個軟體系統行為。
  2. 當一個產品族的多個對象被設計成一起工作時,能夠保證客戶始終只是用同一個產品族中的對象。
  3. 添加新的產品無需修改已有代碼,符合開閉原則。

缺點

  1. 添加新的產品等級結構需要對原有系統進行較大修改,違背了開閉原則。

使用場景

  1. 系統有過個產品族,而每次使用只使用其中一個產品族;
  2. 產品等級結構穩定,設計完成後不會對系統增加或刪除的產品等級結構。

工廠模式總結

  1. 簡單工廠模式隱藏了對象創建細節,將象創建過程與系統業務分離,只需傳入響應參數即可獲得相應對象,缺點是職責過重。
  2. 工廠方法模式引入了抽象工廠,剋服了簡單工廠模式的缺點,將具體對象創建延遲到了子類且可以靈活擴展,但一定程度上造成了系統的類數量膨脹,損耗系統性能。
  3. 抽象工廠模式在工廠方法模式的基礎上進一步擴展,每個具體工廠負責創建多個產品等級結構,減小了工廠方法模式造成的類膨脹問題,提供了系統效率。但是,抽象工廠模式存在開閉原則的傾向性,適用於只需擴展產品族,而產品登記結構穩定的系統。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • react腳手架創建幾種方式 node v16.17.0 npm 8.15.0 yarn 3.2.3 vite 3.1.3 配置less-loader npm 首先通過 npm 方式全局安裝 create-react-app npm install -g create-react-app 查看是否安 ...
  • ==面試題 ##1.vue2中的響應式原理簡述 響應式原理主要就是通過數據劫持,依賴收集,派發更新的方式來實現的 1.數據劫持,vue2是通過Object.defineProperty方法的get、set來將對對象進行遞歸劫持。 其中修改對象的屬性時 就會觸發set, 使用對象的屬性時就會觸發get ...
  • ES6 部分 Typescript 部分 前端工程面經(節流防抖、https、前端攻擊、性能優化...) https://juejin.cn/post/6844903734464495623 ES6面試 為什麼選擇 ES6 ? ES6是新一代的 JS 語言標準,規範了JS的使用標準(var標量提升) ...
  • 問題:【Chrome插件 Chrome extension 】報錯 Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist. 在看一個別人插件的時候發現一個如上所述的報錯,雖然 ...
  • 一、微服務網關概述 如下圖: 不同的微服務一般會有不同的網路地址,客戶端在訪問這些微服務時必須記住幾十甚至幾百個地址,這對於客戶端方來說太複雜也難以維護。如果讓客戶端直接與各個微服務通訊,可能會有很多問題: 客戶端會請求多個不同的服務,需要維護不同的請求地址,增加開發難度 在某些場景下存在跨域請求的 ...
  • 一 、Ribbon概述 Netflixfa 發佈的一個負載均衡器,有助於控制HTTP和TCP客戶端行為。在SpringCloud中,Ribbon提供了客戶端負載均衡的功能,Ribbon自動從服務註冊中心Eureka中讀取到的服務提供者的列表信息(動態獲取服務列表方式),在調用服務節點提供的服務時,基 ...
  • 簡介 對於大部分系統來說,創建對象包括申請記憶體、給成員變數賦值等過程,這些操作耗費的時間基本可以忽略不計。 如果對象中的數據需要經過複雜的計算才能得到(比如排序、計算哈希值),或者需要從 RPC、網路、資料庫、文件系統等非常慢速的 IO 中讀取,這其中耗費的時間有時是無法容忍的。 如果對象的創建成本 ...
  • 建造者模式 介紹 建造者模式註重的是部件構建的過程,意在通過一步一步地精確構造出一個複雜的對象。 可以將建造者模式理解為,假設我們有一個對象需要建立,這個對象是由多個組件(Component)組合而成,每個組件的建立都比較複雜,但運用組件來建立所需的組件對象非常簡單,所以我們就可以將構建複雜組件的步 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...