設計模式-簡單工廠、工廠方法模式、抽象工廠模式詳解

来源:https://www.cnblogs.com/NiceCui/archive/2018/08/02/9408989.html
-Advertisement-
Play Games

工廠方法模式 概要 1. 一個抽象產品類 2. 多個具體產品類 3. 一個抽象工廠 4. 多個具體工廠 每一個具體產品對應一個具體工廠 5. 符合 "OCP開放封閉原則" 優點 1. 降低了代碼耦合度,對象的生成交給子類去完成 2. 實現了開放封閉原則 每次添加子產品 不需要修改原有代碼 缺點 1. ...


工廠方法模式

概要

  1. 一個抽象產品類
  2. 多個具體產品類
  3. 一個抽象工廠
  4. 多個具體工廠 - 每一個具體產品對應一個具體工廠
  5. 符合 - OCP開放封閉原則

image

優點

  1. 降低了代碼耦合度,對象的生成交給子類去完成
  2. 實現了開放封閉原則 - 每次添加子產品 不需要修改原有代碼

缺點

  1. 增加了代碼量,每個具體產品都需要一個具體工廠
  2. 當增加抽象產品 也就是添加一個其他產品族 需要修改工廠 違背OCP

代碼角度進一步解讀

抽象產品類

/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public interface Computer {

    /**
     * 生產電腦
     */
    void createComputer();
}

具體產品

/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class Cpu implements Computer {

    @Override
    public void createComputer() {
        System.out.println("生產cpu");
    }
}
/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class Disk implements Computer {

    @Override
    public void createComputer() {
        System.out.println("生產磁碟disk");
    }
}
/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class Displayer implements Computer {
    @Override
    public void createComputer() {
        System.out.println("生產顯卡displayer");
    }
}

抽象工廠類

/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public interface ComputerFactory {

    /**
     * 工廠方法模式的抽象工廠
     * @return
     */
     Computer getProduct();
}

具體工廠

/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class CpuFactory implements ComputerFactory {

    @Override
    public Computer getProduct() {
        return new Cpu();
    }
}
/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class DiskFactory implements ComputerFactory{
    @Override
    public Computer getProduct() {
        return new Disk();
    }
}
/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class DisplayerFactory implements ComputerFactory {
    @Override
    public Computer getProduct() {
        return new Displayer();
    }
}
/**
 * 客戶端
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class AppClient {

    public static void main(String[] args) {
        ComputerFactory computerFactory = new CpuFactory();
        computerFactory.getProduct().createComputer();

        System.out.println("---------------------------- ");

        computerFactory = new DiskFactory();
        computerFactory.getProduct().createComputer();

        System.out.println("---------------------------- ");

        computerFactory = new DisplayerFactory();
        computerFactory.getProduct().createComputer();

    }
}

列印結果

生產cpu
---------------------------- 
生產磁碟disk
---------------------------- 
生產顯卡displayer

Process finished with exit code 0

抽象工廠模式

概要

  1. 多個抽象產品類
  2. 具體產品類
  3. 抽象工廠類 - 聲明(一組)返回抽象產品的方法
  4. 具體工廠類 - 生成(一組)具體產品

image

優點

  1. 代碼解耦
  2. 實現多個產品族(相關聯產品組成的家族),而工廠方法模式的單個產品,可以滿足更多的生產需求
  3. 很好的滿足OCP開放封閉原則
  4. 抽象工廠模式中我們可以定義實現不止一個介面,一個工廠也可以生成不止一個產品類 對於複雜對象的生產相當靈活易擴展

缺點

1.擴展產品族相當麻煩 而且擴展產品族會違反OCP,因為要修改所有的工廠,例如我們有電腦和滑鼠組成的一個產品族,我們寫完代碼再去添加一個鍵盤就會很麻煩,看完下麵代碼就會理解了

2.由於抽象工廠模式是工廠方法模式的擴展 總體的來說 很笨重

代碼角度進一步解讀

抽象產品

/**
 * 電腦-抽象產品類
 * @author cuishifeng
 * @create 2018-08-02
 **/
public abstract class Computer {

    /**
     * 生產電腦
     */
    public abstract void productComputer();
}
/**
 * 滑鼠 - 抽象產品類
 * @author cuishifeng
 * @create 2018-08-02
 **/
public abstract class Mouse {

    /**
     * 生產滑鼠
     */
    public abstract void productMouse();
}

具體產品

電腦的具體產品

/**
 * PC電腦具體產品類
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class PcComputer extends Computer {

    @Override
    public void productComputer() {
        System.out.println("PC端電腦");
    }
}
/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class ServerComputer extends Computer {

    @Override
    public void productComputer() {
        System.out.println("Server端電腦");
    }
}

滑鼠具體產品

/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class GameMouse extends Mouse {

    @Override
    public void productMouse() {
        System.out.println("游戲滑鼠");
    }
}
/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class OfficeMouse extends Mouse {

    @Override
    public void productMouse() {
        System.out.println("辦公滑鼠");
    }
}

抽象工廠

/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public interface IFactory {

    /**
     * 獲取電腦
     * @return
     */
    Computer getComputer();

    /**
     * 獲取滑鼠
     * @return
     */
    Mouse getMouse();

}

產品A具體工廠

/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class ProductFactoryA implements IFactory {

    @Override
    public Computer getComputer() {
        return new PcComputer();
    }

    @Override
    public Mouse getMouse() {
        return new OfficeMouse();
    }
}

產品B具體工廠

/**
 * @author cuishifeng
 * @create 2018-08-02
 **/
public class ProductFactoryB implements IFactory {
    @Override
    public Computer getComputer() {
        return new ServerComputer();
    }

    @Override
    public Mouse getMouse() {
        return new GameMouse();
    }
}

簡單工廠

概要

  1. 一個抽象產品類
  2. 具體產品類
  3. 一個工廠

優點

  1. 簡單易於實現
  2. 把類的實例化交給工廠,易於解耦

缺點

1.添加具體產品需要修改工廠 違反OCP開放封閉原則

代碼角度進一步解讀

抽象產品類

/**
 * @author cuishifeng
 * @create 2018-07-09
 **/
public interface Car {

    /**
     * 我有一輛什麼車
     */
     void myCar();
}

具體產品

/**
 * @author cuishifeng
 * @create 2018-07-09
 **/

public class BenChiCar implements Car {


    @Override
    public void myCar() {
        System.out.println("我有一輛賓士車!");
    }
}
public class FerrariCar implements Car {

    @Override
    public void myCar() {
        System.out.println("我有一輛法拉利!");
    }
}
public class LamborghiniCar implements Car {
    @Override
    public void myCar() {
        System.out.println("我有一輛蘭博基尼!");
    }
}

工廠類

public class CarFactory {

    public static Car createCar(String carName){
        if (carName == null){
            return null;
        }
        switch (carName){
            case "BenChiCar":
                return new BenChiCar();
            case "FerrariCar":
                return new FerrariCar();
            case "LamborghiniCar":
                return new LamborghiniCar();
            default:
                return null;
        }
    }
}
Car car = CarFactory.createCar("BenChiCar");
car.myCar();

Car car2 = CarFactory.createCar("FerrariCar");
car2.myCar();

輸出

我有一輛賓士車!
我有一輛法拉利!

總結

簡單工廠模式最大的有點就是工廠內有具體的邏輯去判斷生成什麼產品,將類的實例化交給了工廠,這樣當我們需要什麼產品只需要修改客戶端的調用而不需要去修改工廠,對於客戶端來說降低了與具體產品的依賴

工廠方法模式是簡單工廠的擴展,工廠方法模式把原先簡單工廠中的實現那個類的邏輯判斷交給了客戶端,如果像添加功能只需要修改客戶和添加具體的功能,不用去修改之前的類。

抽象工廠模式進一步擴展了工廠方法模式,它把原先的工廠方法模式中只能有一個抽象產品不能添加產品族的缺點剋服了,抽象工廠模式不僅僅遵循了OCP原則(對擴展開放,對修改關閉),而且可以添加更多產品(抽象產品),具體工廠也不僅僅可以生成單一產品,而是生成一組產品,抽象工廠也是聲明一組產品,對應擴展更加靈活,但是要是擴展族系就會很笨重。


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

-Advertisement-
Play Games
更多相關文章
  • 看了很多關於TypeScript的文章,總體說來沒有很好的,一個系統的學習TypeScript的資源。 接下來,我將給大家帶來TypeScript的系列,讓你和我一樣,一步一步的學習TypeScript,並且學以致用。 什麼是TypeScript呢 在TypeScript的官方網站上面有這樣的描述:... ...
  • 代碼可以在 https://pan.baidu.com/s/1uN120-18hvAzELpJCQfbXA 處下載 開始,創建一個paiziDm 的分支 git checkout -b paiziDm ,我們再寫代碼 下麵來 分析思路 就是模擬點擊 換徽章 的過程,如果沒有當前房間的徽章,則不戴。 ...
  • 最近開發小程式,為瞭解耦數據 寫了一個wenaox的庫,一開始放在libs里使用相對路徑引入,覺得很辛苦, 後面發現小程式的npm已經進入beta版本,於是下載了beta開發工具,構建後就可以直接import引入 很爽 有需要可以下載用一下 [Wenaox][wenaox url] [![NPM v ...
  • Javascript是一種基於對象的語言,你遇到的所有東西幾乎都是對象。但是,它又不是一種真正的面向對象編程(OOP)語言,因為它的語法中沒有Class。(不過,ES6引入了Class這個概念,作為對象的模板。通過class關鍵字,可以定義類。ES6入門:http://es6.ruanyifeng. ...
  • 1、代碼: <!DOCTYPE html><html><head> <meta charset="utf-8"> <title>JS過渡和變形效果演示</title> <style type="text/css"> *{ margin: 0; padding: 0; } .container{ wi ...
  • 1:children及find方法都用是用來獲得element的子elements的,兩者都不會返回 text node,就像大多數的jQuery方法一樣。 2:children方法獲得的僅僅是元素一下級的子元素,即:immediate children。 3:find方法獲得所有下級元素,即:de ...
  • CSS 的偽類選擇器和偽元素選擇器,讓 CSS 有了更為強大的功能。 偽類大家聽的多了,偽元素可能聽到的不是那麼頻繁,其實 CSS 對這兩個是有區分的。 有個錯誤有必要每次講到偽類都提一下,有時你會發現偽類元素使用了兩個冒號 (::) 而不是一個冒號 (:),這是 CSS3 規範中的一部分要求,目的 ...
  • 很多時候我們需要引入框架來開發項目,這時我們可能會遇到頁面還沒載入完源碼出來了的問題,給用戶一種不好的視覺體驗,這是便需要loading載入了,來完善用戶體驗! ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...