【技術積累】軟體設計模式中的工廠模式【一】

来源:https://www.cnblogs.com/yyyyfly1/archive/2023/06/13/17476809.html
-Advertisement-
Play Games

博客推行版本更新,成果積累制度,已經寫過的博客還會再次更新,不斷地琢磨,高質量高數量都是要追求的,工匠精神是學習必不可少的精神。因此,大家有何建議歡迎在評論區踴躍發言,你們的支持是我最大的動力,你們敢投,我就敢肝 ...


什麼是工廠模式?

工廠模式是一種設計模式,它利用工廠類來創建對象,而不是在程式中直接實例化對象。

工廠模式可以隱藏創建對象的具體細節,提高代碼可維護性和可擴展性。

其核心思想是將對象的創建與具體實現分離開來,通過工廠類統一管理對象的創建,使得客戶端無需瞭解創建對象的具體實現。

工廠類根據客戶端請求的不同,返回不同的對象實例。

工廠模式主要包括三種方式:簡單工廠模式、工廠方法模式和抽象工廠模式。

什麼是簡單工廠模式?

簡單工廠模式(Simple Factory Pattern),又稱靜態工廠模式,是一種常見的設計模式之一,它是由一個工廠對象決定創建出哪一種產品類的實例,而客戶端不需要知道具體實現類的類名,只需要知道所需產品的類型即可。

簡單工廠模式的核心思想是將多個具有共同特征的產品類抽象成一個產品類,並創建一個工廠類來生成這些產品的實例。

這樣,客戶端只需要傳遞一個參數給工廠類即可實現創建實例的功能,使得客戶端與具體實現類解耦,使得後期維護更加方便。

 

好比去餐廳吃飯,你只需要跟服務員點菜(請求產品),告訴服務員你想要吃什麼菜(指定對象類型),服務員就會為你送上菜(返回對象)。

你不需要知道菜是如何做出來的(對象是如何創建的),只需要享受美食。

這就是簡單工廠模式對於對象的創建過程進行了封裝,讓使用者不需要知道具體的實現過程,更加方便快捷。

// 定義產品抽象類
abstract class Product {
    public abstract void use();
}
// 定義具體產品類
class ProductA extends Product {
    public void use() {
        System.out.println("使用產品A");
    }
}
class ProductB extends Product {
    public void use() {
        System.out.println("使用產品B");
    }
}
// 定義工廠類
class Factory {
    public static Product createProduct(String type) {
        if (type.equals("A")) {
            return new ProductA();
        } else if (type.equals("B")) {
            return new ProductB();
        } else {
            return null;
        }
    }
}
// 客戶端使用工廠來創建產品實例
public static void main(String[] args) {
    Product product = Factory.createProduct("A");
    product.use();
}

簡單工廠模式的優點和缺點

簡單工廠模式(Simple Factory Pattern)是一種創建型設計模式,它提供了一種簡單、通用的方式來創建對象,實現了對客戶端代碼的解耦使得客戶端不需要知道對象的具體實現。下麵分別詳細介紹簡單工廠模式的優點和缺點,以及分別用Java偽代碼演示。

優點:

1. 降低客戶端的耦合度:客戶端只需要知道工廠類即可,不需要知道具體的產品類,使得客戶端代碼與具體類的實現解耦。

2. 客戶端不需要知道對象的創建過程:只需要知道工廠類提供的介面即可,無需瞭解具體對象的創建過程,使得客戶端更加容易使用產品類。

3. 工廠方法有利於橫向擴展:可以很容易擴展出新的產品類,只需要編寫新的產品子類和工廠方法即可。

缺點:

1. 工廠類的職責相對較重,不易於擴展:如果需要添加新的產品類,需要修改工廠類的代碼,可能會引起潛在的風險。

2. 不符合開閉原則:增加新的產品需要修改工廠類的代碼,不符合開閉原則。

3. 簡單工廠類只能創建單一類型的產品,無法滿足多種產品的需求。

 Java偽代碼演示簡單工廠模式

//先定義一個抽象產品介面:

public interface Product {
    void run();
}

//再定義具體產品類:


public class ProductA implements Product {
    @Override
    public void run() {
        System.out.println("ProductA is running.");
    }
}

public class ProductB implements Product {
    @Override
    public void run() {
        System.out.println("ProductB is running.");
    }
}


//定義一個簡單的工廠類:


public class SimpleFactory {
    public static Product createProduct(int type) {
        if (type == 1) {
            return new ProductA();
        } else if (type == 2) {
            return new ProductB();
        } else {
            return null;
        }
    }
}

優點的演示:

public class Client {
    public static void main(String[] args) {
        Product product = SimpleFactory.createProduct(1);
        if (product != null) {
            product.run();
        } else {
            System.out.println("Invalid type.");
        }
    }
}

這樣就可以實現客戶端代碼與具體類的實現解耦,客戶端只需要知道工廠類即可。

缺點的演示:

public class Client {
    public static void main(String[] args) {
        Product product = SimpleFactory.createProduct(3);
        if (product != null) {
            product.run();
        } else {
            System.out.println("Invalid type.");
        }
    }
}

當傳入參數為3時,會返回null,表示無效的類型,這樣就需要修改工廠類的代碼,不符合開閉原則。

簡單工廠模式的組成部分和工作流程是什麼?如何創建一個簡單工廠模式

簡單工廠模式的組成部分包括:

  1. 工廠類:負責創建產品的類,通常是一個靜態工廠方法,根據不同的參數生成不同的產品。
  2. 抽象產品類:定義產品的抽象方法或介面,是具體產品類的父類。
  3. 具體產品類:實現抽象產品類定義的方法或介面,是由工廠類創建的產品。

簡單工廠模式的工作流程是:

  1. 客戶端通過調用工廠類的靜態工廠方法並傳遞相應的參數,請求創建產品。
  2. 工廠類根據傳遞的參數創建對應的具體產品類實例。
  3. 工廠類將創建的產品返回給客戶端。
  4. 客戶端使用產品實例執行相應的操作。

下麵是簡單工廠模式的實現步驟:

  1. 創建一個抽象產品介面:定義了所有產品必須實現的方法。
  2. 創建具體產品類:實現抽象產品介面,並定義特定於該產品的方法。
  3. 創建一個工廠類:工廠類包含一個用於創建產品的方法。該方法接受一個參數(通常是一個枚舉值或一個字元串),根據參數值的不同返回不同的具體產品對象。
  4. 在客戶端代碼中使用工廠類:通過調用工廠類的靜態方法,根據需要獲取產品。

 代碼可參照上一個問題的案例

簡單工廠模式適用於哪些場景

簡單工廠模式適用於以下場景:

  1. 需要創建的對象較少,通常不超過5個。
  2. 對象的生成過程比較簡單,只需要根據輸入參數選擇不同的構造方式即可。
  3. 客戶端不需要知道對象的具體類名,只需要知道對象的類型即可。
  4. 不需要通過繼承來實現不同產品之間的差異,只需要通過同一個工廠來創建不同類型的產品即可。
  5. 最初設計時不確定對象會有哪些具體的子類,但仍然需要通過某種方式來創建這些對象。這時可以先在工廠中添加這些對象,後續再根據需求修改工廠的實現。

總之,簡單工廠模式適合於對象較少、生成過程簡單、無需知道具體類名、不需要通過繼承來實現差異、允許動態修改工廠實現等情況。但是,隨著業務增長,可能會變得難以維護,因為所有的創建邏輯都在一個工廠中,容易導致代碼量增加、邏輯複雜等問題。因此,在選擇使用簡單工廠模式時應該註意這些風險,並考慮是否需要更複雜的創建模式來滿足業務需求。

簡單工廠模式客戶端如何處理產品對象的創建異常

簡單工廠模式是一種創建型設計模式,其目的是在不暴露創建邏輯的情況下創建對象。但是,當創建過程中出現異常時,客戶端需要處理異常,以避免應用程式崩潰。

在簡單工廠模式中,客戶端通過工廠類創建產品對象。如果創建過程中出現異常,則工廠類需要拋出異常。客戶端可以捕獲異常,並相應地處理它。

假設有一個形狀工廠類,它可以創建不同類型的形狀,例如圓形、矩形和三角形。客戶端通過提供形狀類型來請求創建相應的形狀對象。

public class ShapeFactory {
    public Shape createShape(String shapeType) throws InvalidShapeException {
        switch (shapeType) {
            case "circle":
                return new Circle();
            case "rectangle":
                return new Rectangle();
            case "triangle":
                return new Triangle();
            default:
                throw new InvalidShapeException("Invalid shape type provided: " + shapeType);
        }
    }
}

在這個工廠類中,如果客戶端提供一個無效的形狀類型,則會拋出一個無效形狀異常(InvalidShapeException)。客戶端可以通過捕獲此類異常來處理創建過程中的異常。以下是客戶端如何處理異常的示例偽代碼

try {
    ShapeFactory shapeFactory = new ShapeFactory();
    Shape circle = shapeFactory.createShape("circle");
    Shape rectangle = shapeFactory.createShape("rectangle");
    Shape triangle = shapeFactory.createShape("triangle");
    Shape square = shapeFactory.createShape("square"); //Invalid Shape Type
} catch (InvalidShapeException e) {
    System.out.println(e.getMessage());
}

在上述示例中,當客戶端請求創建一個無效形狀時,工廠類將拋出一個InvalidShapeException。客戶端通過捕獲此異常並列印其消息來處理創建過程中的異常。

通過這種方式,客戶端可以在簡單工廠模式中處理異常,並且可以使應用程式從異常中恢復。

抽象工廠模式是什麼

抽象工廠模式是一種創建型設計模式,它提供介面用於創建一系列相關或依賴對象,而不需要指定它們的具體類。抽象工廠模式允許客戶端使用抽象介面和實現介面分離的方式來創建一組相關的對象。

抽象工廠模式中包含抽象工廠、具體工廠、抽象產品和具體產品四個角色。

  1. 抽象工廠定義了一組用於創建抽象產品的介面
  2. 具體工廠實現了抽象工廠中定義的介面,用於生產一組具體產品
  3. 抽象產品定義了一組用於操作產品的介面
  4. 具體產品實現了抽象產品中定義的介面。

使用抽象工廠模式,如果需要增加一種產品系列,則只需添加一個新的具體工廠和一組具體產品,而不需要改變已有的代碼。

這種模式可以有效地減少代碼的耦合性,提高系統的擴展性和靈活性。

抽象工廠模式就是一個廠家能夠生產多個系列產品,例如一個化妝品公司可以生產多個系列的護膚品和化妝品。

為了讓生產過程更加標準和規範化,該公司會設計多個生產線,每條生產線專門生產一種系列產品。每條生產線里都有專門的設備和加工工藝,不能互相混用,例如生產基礎護膚品的生產線不能生產高端抗衰老護膚品。

這時,抽象工廠模式就很適用了。該公司設計一個抽象工廠介面,用於生產一類產品,然後各個生產線分別實現該介面,並且生產出來的產品都要符合該介面標準。這樣,不同生產線之間可以互相替換,客戶端也無需知道具體的生產過程,只需通過訪問抽象工廠介面來獲取需要的產品就可以了。

//首先,定義產品族的抽象基類 AbstractProductA 和 AbstractProductB:


public abstract class AbstractProductA {
    public abstract void use();
}

public abstract class AbstractProductB {
    public abstract void eat();
}


//然後,定義不同產品的具體實現類 ProductA1、ProductA2、ProductB1 和 ProductB2:


public class ProductA1 extends AbstractProductA {
    public void use() {
        System.out.println("Product A1 is used");
    }
}

public class ProductA2 extends AbstractProductA {
    public void use() {
        System.out.println("Product A2 is used");
    }
}

public class ProductB1 extends AbstractProductB {
    public void eat() {
        System.out.println("Product B1 is eaten");
    }
}

public class ProductB2 extends AbstractProductB {
    public void eat() {
        System.out.println("Product B2 is eaten");
    }
}


//接著,定義抽象工廠介面 AbstractFactory,包含用於創建產品族的介面方法:

public interface AbstractFactory {
    public AbstractProductA createProductA();
    public AbstractProductB createProductB();
}


//然後,定義具體的工廠類 ConcreteFactory1 和 ConcreteFactory2,分別實現 AbstractFactory 介面並實現其中的方法:


public class ConcreteFactory1 implements AbstractFactory {
    public AbstractProductA createProductA() {
        return new ProductA1();
    }
    public AbstractProductB createProductB() {
        return new ProductB1();
    }
}

public class ConcreteFactory2 implements AbstractFactory {
    public AbstractProductA createProductA() {
        return new ProductA2();
    }
    public AbstractProductB createProductB() {
        return new ProductB2();
    }
}

//最後,客戶端只需要訪問抽象工廠介面,具體工廠的實例化和具體產品的創建都被封裝到工廠內部:

public class Client {
    public static void main(String[] args) {
        AbstractFactory factory1 = new ConcreteFactory1();
        AbstractProductA productA1 = factory1.createProductA();
        AbstractProductB productB1 = factory1.createProductB();
        productA1.use();
        productB1.eat();

        AbstractFactory factory2 = new ConcreteFactory2();
        AbstractProductA productA2 = factory2.createProductA();
        AbstractProductB productB2 = factory2.createProductB();
        productA2.use();
        productB2.eat();
    }
}

//輸出結果為:

Product A1 is used
Product B1 is eaten
Product A2 is used
Product B2 is eaten

//這樣,就通過抽象工廠模式創建了不同的產品族,並且客戶端與具體產品類實現解耦了。

抽象工廠模式與簡單工廠模式的區別

抽象工廠模式和簡單工廠模式都是面向對象的創建型設計模式,它們的主要區別在於以下幾個方面:

1.抽象工廠模式可以創建一系列關聯的產品,而簡單工廠只能創建一個產品。

2.在抽象工廠模式中,有多個抽象產品類,每個抽象產品類可以有多個具體產品類實現,而簡單工廠模式中,只有一個抽象產品類和一個具體產品類。

3.抽象工廠模式通常是面向一個產品等級結構的,可以擴展不同的產品系列,而簡單工廠模式是面向單一產品的。

4.抽象工廠模式要求客戶端代碼使用抽象介面來創建一組相關的產品對象,而簡單工廠模式僅需要一個傳遞一些參數和一個實例化對象。

5.抽象工廠模式的適用範圍比簡單工廠模式更廣,但實現抽象工廠模式的成本也更高。簡單工廠模式較為簡單易懂,易於使用和實現。

總之,抽象工廠模式適用於需求變動較頻繁,需要同時創建多個產品族的場景。而簡單工廠模式適用於創建單一產品,且該產品創建的邏輯不隨需求變動。

綜上所述,抽象工廠模式和簡單工廠都有自己的特點和應用場景,需要根據具體需求選擇合適的工廠模式來實現代碼。

在黑夜裡夢想著光,心中覆蓋悲傷,在悲傷里忍受孤獨,空守一絲溫暖。 我的淚水是無底深海,對你的愛已無言,相信無盡的力量,那是真愛永在。 我的信仰是無底深海,澎湃著心中火焰,燃燒無盡的力量,那是忠誠永在。
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 隨著業務的發展及版本迭代,客戶端工程中不斷增加新的業務邏輯、引入新的資源,隨之而來的問題就是安裝包體積變大,前期各個業務模塊通過無用資源刪減、大圖壓縮或轉上雲、AB實驗業務邏輯下線或其他手段在降低包體積上取得了一定的成果。 ...
  • 本期直播《“元”來如此,“服務”直達——揭秘鴻蒙新流量陣地》聚焦**元服務**的**商業流量價值**,介紹元服務提供的服務直達和卡片動態變化等**輕量化服務**。網約停車旗艦平臺小強停車做客直播間,分享小強停車在HarmonyOS生態中,如何通過元服務為廣大用戶帶來更加便捷易用的線上預約停車體驗。快 ...
  • ## 顏色 1. **RGB** (紅,綠,藍)三種顏色的集合,最低值是0(十六進位00)到最高值255(十六進位FF) 2. **HSL** H色相(0-360),S飽和度(百分比),L亮度(百分比) 3. (不)透明度 **rgba、hsla** (新版瀏覽器可不寫a,直接寫4個值) ## li ...
  • ### 前言 前不久,在我的一個項目中,需要展示一個橫向滾動的標簽頁,它支持滑鼠橫向拖動和點擊切換。在實現的過程中,我發現這個小功能需要同時用到前端的三輛馬車,但是實現難度不高,而且最終效果還不錯,是個難得的初學者項目,於是萌生了寫這篇文章的想法,希望對初學者有所幫助。同時為了避免初學者學習框架,我 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 使用背景: 1.因為svg圖標在任何設備下都可以高清顯示,不會模糊。而icon會在顯卡比較低的電腦上有顯示模糊的情況 2.svg圖標在頁面render時 速度會比icon稍微快一點 3.實現小程式換膚功能 ;方案見:www.yuque.c ...
  • 博客推行版本更新,成果積累制度,已經寫過的博客還會再次更新,不斷地琢磨,高質量高數量都是要追求的,工匠精神是學習必不可少的精神。因此,大家有何建議歡迎在評論區踴躍發言,你們的支持是我最大的動力,你們敢投,我就敢肝 ...
  • 前幾天打算給博客添加一個圖片預覽的效果,可在網上找了半天也沒找到合適的庫,於是自己乾脆自己手寫了個。 ...
  • # CSS特性 ## 1、繼承性 ##### 特性: 1、子元素有預設繼承父元素樣式的特點(**子承父業**) 2、可以繼承的常見屬性(文字控制屬性都可以繼承) 1.color 2.font-style、font-weight、font-size、font-family 3.text-indent, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...