1. 程式人生 > >設計模式的征途—2.簡單工廠(Simple Factory)模式

設計模式的征途—2.簡單工廠(Simple Factory)模式

  工廠模式是最常用的一種建立型模式,通常所說的工廠模式一般是指工廠方法模式。本篇是是工廠方法模式的“小弟”,我們可以將其理解為工廠方法模式的預備知識,它不屬於GoF 23種設計模式,但在軟體開發中卻也應用地比較頻繁。此外,工廠方法模式還有一位“大哥”—抽象工廠模式,會在後面進行介紹。

簡單工廠模式(Simple Factory) 學習難度:★★☆☆☆ 使用頻率:★★★☆☆

一、從一個圖表庫談起

  M公司想要基於C#語言開發一套圖表庫,該圖表庫可以為應用系統提供各種不同外觀的圖示,例如柱狀圖、餅狀圖或折線圖等。M公司圖表庫設計開發人員希望為應用系統開發人員提供一套靈活易用的圖表庫,而且可以較為方便地對圖表庫進行擴充套件,以便於在將來增加一些新型別的圖表。

  M公司的程式設計師提出了一個初始設計方案,將所有圖表的實現程式碼封裝在一個Chart類中,其框架程式碼如下所示:

    public class Chart
    {
        private string type; // 圖表型別

        public Chart(object[][] data, string type)
        {
            this.type = type;

            if (this.type.Equals("histogram", StringComparison.OrdinalIgnoreCase))
            {
                
// 初始化柱狀圖 } else if (this.type.Equals("pie", StringComparison.OrdinalIgnoreCase)) { // 初始化餅狀圖 } else if (this.type.Equals("line", StringComparison.OrdinalIgnoreCase)) { // 初始化折線圖 } }
public void Display() { if (this.type.Equals("histogram", StringComparison.OrdinalIgnoreCase)) { // 顯示柱狀圖 } else if (this.type.Equals("pie", StringComparison.OrdinalIgnoreCase)) { // 顯示餅狀圖 } else if (this.type.Equals("line", StringComparison.OrdinalIgnoreCase)) { // 顯示折線圖 } } }

  客戶端程式碼通過呼叫Chart類的建構函式來建立圖表物件,根據引數type的不同可以得到不同型別的圖示,然後再呼叫Display()方法來顯示相應的圖表。

  但是,不難看出,Chart類是一個巨大的類,存在很多問題:

  • 在Chart類中包含很多if-else程式碼塊,相當冗長,可讀性很差;
  • Chart類的職責過重,負責初始化和顯示各種圖表物件,違反了單一職責原則;
  • 當需要增加新的圖表型別時,必須修改Chart類的原始碼,違反了開閉原則;
  • 客戶端只能通過new關鍵字來直接建立Chart物件,Chart類與客戶端類耦合度較高,物件的建立和使用無法分離;
  • 客戶端在建立Chart物件之前可能還需要進行大量初始化設定,例如設定柱狀圖的顏色和高度等,如果在Chart類的建構函式中沒有提供一個預設設定,那就只能由客戶端來完成初始設定,這些程式碼在每次建立Chart物件時都會出現,導致程式碼的重複;

二、簡單工廠模式概述

2.1 要點

  簡單工廠模式並不屬於GoF 23種經典設計模式,但通常將它作為學習其他工廠模式的基礎。

簡單工廠(Simple Factory)模式:定義一個工廠類,它可以根據引數的不同返回不同類的例項,被建立的例項通常都具有共同的父類。因為在簡單工廠模式中用於建立例項的方法是靜態(static)方法,因此簡單工廠模式又被稱為靜態工廠方法模式,它屬於建立型模式。

  簡單工廠模式的要點在於:當你需要什麼,只需要傳入一個正確的引數,就可以獲取你所需的物件,而無須知道其建立細節

2.2 結構圖

  簡單工廠模式包含3個角色:

  • Factory - 工廠角色:該模式的核心,負責實現建立所有產品例項的內部邏輯,提供一個靜態的工廠方法GetProduct(),返回抽象產品型別Product的例項。
  • Product - 抽象產品角色:所有產品類的父類,封裝了各種產品物件的共有方法,它的引入將提高系統的靈活性,使得在工廠類中只需要定義一個通用的工廠方法,因為所有建立的具體產品物件都是其子類物件。
  • ConcreteProduct - 具體產品角色:簡單工廠模式的建立目標,所有被建立的物件都充當這個角色的某個具體類的例項。

  在簡單工廠模式中,客戶端通過工廠類來建立一個產品類的例項,而無須直接使用new關鍵字來建立物件。(可以看出,它是工廠模式家族中最簡單的一員)

三、重構圖表庫的實現

3.1 新的結構圖

  為了將Chart類的職責分離,同時將Chart物件的建立和使用分離,M公司開發人員決定使用簡單工廠模式對圖表庫進行重構,重構後的結構圖如下所示:

3.2 新的程式碼實現

  (1)抽象產品角色:IChartable介面

    public interface IChartable
    {
        void Display();
    }

  (2)具體產品角色:各種圖表型別

    public class HistogramChart : IChartable
    {
        public HistogramChart()
        {
            Console.WriteLine("建立柱狀圖...");
        }

        public void Display()
        {
            Console.WriteLine("顯示柱狀圖...");
        }
    }

    public class LineChart : IChartable
    {
        public LineChart()
        {
            Console.WriteLine("建立折線圖...");
        }

        public void Display()
        {
            Console.WriteLine("顯示折線圖...");
        }
    }

    public class PieChart : IChartable
    {
        public PieChart()
        {
            Console.WriteLine("建立餅狀圖...");
        }

        public void Display()
        {
            Console.WriteLine("顯示餅狀圖...");
        }
    }

  (3)工廠角色:ChartFactory

    public class ChartFactory
    {
        public static IChartable GetChart(string type)
        {
            IChartable chart = null;

            if (type.Equals("histogram", StringComparison.OrdinalIgnoreCase))
            {
                chart = new HistogramChart();
                Console.WriteLine("初始化設定柱狀圖...");
            }
            else if (type.Equals("pie", StringComparison.OrdinalIgnoreCase))
            {
                chart = new PieChart();
                Console.WriteLine("初始化設定餅狀圖...");
            }
            else if (type.Equals("line", StringComparison.OrdinalIgnoreCase))
            {
                chart = new PieChart();
                Console.WriteLine("初始化設定折線圖...");
            }

            return chart;
        }
    }

  (4)客戶端呼叫:

    public static void Main()
    {
        IChartable chart = ChartFactory.GetChart("histogram");
        if (chart != null)
        {
            chart.Display();
        }

        chart = ChartFactory.GetChart("pie");
        if (chart != null)
        {
            chart.Display();
        }
    }

  執行結果如下:

  

  在客戶端程式碼中,使用工廠類的靜態方法來建立具體產品物件,如果需要更換產品,只需要修改靜態工廠方法中的引數即可。例如:將柱狀圖改為餅狀圖,只需要將程式碼:

IChartable chart = ChartFactory.GetChart("histogram");

  改為:

IChartable chart = ChartFactory.GetChart("pie");

3.3 改進的方案

  M公司開發人員發現在建立具體Chart物件時,每次更換一個Chart物件都需要修改客戶端中靜態工廠方法的引數,客戶端程式碼需要重新編譯,這對於客戶端而言,是違反了開閉原則的。於是,開發人員希望有一種方法能夠在不修改客戶端程式碼地前提下更換具體產品物件。

  因此,他們考慮使用配置檔案(XML)來實現:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="charttype" value="histogram"/>
  </appSettings>
</configuration>

  客戶端因此改為:

    public static void Main()
    {
        string type = AppConfigHelper.GetChartType(); // 讀取配置檔案中的charttype
        if (string.IsNullOrEmpty(type))
        {
            return;
        }

        IChartable chart = ChartFactory.GetChart(type);
        if (chart != null)
        {
            chart.Display();
        }
    }

  執行結果如下:

  

四、簡單工廠模式總結

4.1 主要優點

  • 實現了物件建立和使用的分離:客戶端可以免除直接建立產品物件的職責,而僅僅“消費”產品。
  • 客戶端無須知道所建立的具體產品類的類名,只需要知道具體產品類所對應的的引數即可。
  • 通過引入配置檔案,可以在不修改任何客戶端程式碼地情況下更換和增加新的具體產品類,在一定程度上提高了系統的靈活性。

4.2 主要缺點

  • 由於工廠類集中了所有產品的建立邏輯,職責過重,一旦不能正常工作,整個系統都要受影響。
  • 使用簡單工廠模式勢必會增加系統中類的個數(引入新的工廠類),增加了系統的複雜度和理解難度。
  • 系統擴充套件困難,一旦新增新產品就不得不修改工廠邏輯,在產品型別較多時,有可能會造成工廠邏輯過於複雜,不利於系統的擴充套件和維護。
  • 簡單工廠模式由於使用了靜態工廠方法,造成工廠角色無法形成基於繼承的等級結構。

4.3 適用場景

  • 工廠類負責建立的物件比較少,由於建立的物件較少,不會造成工廠方法中的業務邏輯太過複雜。
  • 客戶端只需要知道傳入工廠類的引數,對於如何建立物件並不關心。

參考資料

      DesignPattern

  劉偉,《設計模式的藝術—軟體開發人員內功修煉之道》

作者:周旭龍

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連結。

相關推薦

設計模式征途2.簡單工廠Simple Factory模式

  工廠模式是最常用的一種建立型模式,通常所說的工廠模式一般是指工廠方法模式。本篇是是工廠方法模式的“小弟”,我們可以將其理解為工廠方法模式的預備知識,它不屬於GoF 23種設計模式,但在軟體開發中卻也應用地比較頻繁。此外,工廠方法模式還有一位“大哥”—抽象工廠模式,會在後面進行介紹。 簡單工廠

設計模式2——建立型——工廠相關:簡單工廠Simple factory工廠方法Factory method,抽象工廠Abstract factory

概要 這裡試圖描述23個設計模式中的兩個工廠(Factory)相關的設計模式:工廠方法(Factorymethod),抽象工廠(Abstract factory)。 注意點: 這兩個都屬於建立型設計模式。 由於這兩個設計模式都

設計模式征途—4.抽象工廠Abstract Factory模式

上一篇的工廠方法模式引入了工廠等級結構,解決了在原來簡單工廠模式中工廠類職責太重的原則,但是由於工廠方法模式的每個工廠只生產一類產品,可能會導致系統中存在大量的工廠類,從而增加系統開銷。那麼,我們應該怎麼來重構?似乎,我們可以考慮將一些相關的產品組成一個“產品族”,由同一個工廠來統一生產,這就是本次將要學習的

抽象工廠Abstract Factory模式——Java設計模式

抽象工廠模式簡介 抽象工廠模式(Abstract Factory Pattern):圍繞一個超級工廠建立其他工廠。該超級工廠又稱為其他工廠的工廠。 分類:建立型模式。 在抽象工廠模式中,介面是負責

設計模式簡單工廠模式Simple Factory

思想 簡單工廠模式,因為用於建立例項的方法是靜態的,又稱為靜態工廠方法模式。在該模式中,可以根據引數的不同返回不同類的例項。簡單工廠模式專門定義一個類來負責建立其他類的例項,被建立的例項通常都具有相同的父類。 結構 組成(角色) 作用

JAVA設計模式01:建立型-工廠模式簡單工廠模式Simple Factory

     工廠模式是最常用的一類建立型設計模式,通常我們所說的工廠模式是指工廠方法模式,它也是使用頻率最高的工廠模式。本章將要學習的簡單工廠模式是工廠方法模式的“小弟”,它不屬於GoF 23種設計模式,但在軟體開發中應用也較為頻繁,通常將它作為學習其他工廠模式的入門。此

設計模式征途—17.模板方法Template Method模式

opened res ati 相同 rom 配置 version factor creat 在現實生活中,很多事情都需要經過幾個步驟才能完成,例如請客吃飯,無論吃什麽,一般都包含:點單、吃東西、買單等幾個步驟,通常情況下這幾個步驟的次序是:點單=>吃東西=>買單

我的設計模式-抽象工廠Abstract Factory

抽象工廠主要是在工廠模式的基礎上,將物件例項生成工廠進行了抽象,增加了物件例項生成工廠的拓展性。 工廠模式可以參看: 以下舉例說明抽象工廠模式: 可能有多種印表機,但都有列印方法; 將原有工廠模式的印表機工廠類進行封裝,通過實現統一的介面來實現不同的印表機例項的

藍芽簡單配對Simple Pairing協議及程式碼流程簡述

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

【java設計模式】之 模板方法Template Method模式

1. 模板方法的一個例項         這一節主要來學習一下設計模式中的模板方法模式。我們先來看一個例子:假如現在老闆讓你做一個汽車的模型,要求只要完成基本功能即可,不考慮擴充套件性,那你會怎麼做呢?我們首先會根據經驗設計一個類圖:        由這個類圖可知,非

抽象工廠Abstract Factory

工廠 cnblogs null pro pes reg 抽象 blog log 抽象工廠模式是工廠模式的升級版,用於創建一組相關或者相互依賴的對象 // 抽象工廠模式 function Car (name, color) { this.name = name;

設計模式簡單工廠模式simple factory pattern)

什麼是簡單工廠模式, 舉個不恰當的例子, 就說生產雪糕吧, 雪糕什麼形狀的都有, 有長方形,有圓形等等, 怎麼生產呢? 首先肯定是先造個機器, 然後弄幾個按鈕,上面依次寫上長方形, 圓形等等,我按長方形就給我出長方形的, 我按圓形的按鈕就給我出圓形的。 大概就是這樣接下來

設計模式 (四)——簡單工廠模式Simple Factory,建立型

1.概述 使用設計模式可以提高程式碼的可複用性、可擴充性和可維護性。簡單工廠模式(Simple Factory Pattern)屬於建立型模式。簡單工廠模式,由一個工廠物件決定創建出哪一種產品類的例項,它經常被用於封裝建立物件的程式碼。 簡單工廠模式類圖結構

設計模式學習筆記--簡單工廠模式Simple Factory Pattern【建立型模式

簡單工廠模式: 工廠是用來生成產品的,簡單工廠,說明工廠能力有限因此只生成一個系列的產品。 此係列產品提供一個產品抽象,具體的產品在派生產品中進行實現。 簡單工廠(一個類),用來管理這個系列產品的生產。工廠中會有一個creat(char* name)成員函式name是需要生

設計模式-3簡單工廠模式Simple Factory Pattern

一、引言 在面向物件程式設計中, 最通常的方法是一個new操作符產生一個物件例項,new操作符就是用來構造物件例項的。但是在一些情況下, new操作符直接生成物件會帶來一些問題。舉例來說, 許多型別物件的創造需要一系列的步驟: 你可能需要計算或取得物件的初始

易學設計模式看書筆記(2) - 簡單工廠模式

原理 pub -m post 繼承 void cto tracking else if 本文摘自易學設計模式一書 一、簡單工廠模式 1.動物管理系統的樣例 public interface Animal{ public void eat(); } publi

原創我眼中的設計模式系列之簡單工廠模式(一)

int 業務 text 們的 acc 現在 rgs sub reat 簡單工廠模式   在日常的軟件開發中,我們一般都是按照模塊來劃分工作的。 場景一:   試想我們現在有這麽一個模塊,為其他的模塊提供服務,比如說我們調用了好幾個外部接口,統一返回XML字符串,每個接口返回

c++建立型設計模式--工廠模式--簡單工廠單個產品的構建

思想 主要是對於單個簡單的產品進行構建 基類 #pragma once #include <iostream> /** * 基類指標 *Date :[10/12/2018 ] *Aut

《大話設計模式》之簡單工廠模式Java版

##導火線: “請用C++、Java、C#或VB.NET任意一種面嚮物件語言實現一個計算器控制檯程式,要求輸入兩個數和運算子號,得到結果。” #菜鳥階段的程式設計: public class demo { public static void m

設計模式簡單介紹Java語言-- 工廠方法模式

設計模式簡單介紹(Java語言) – 工廠方法模式 1.工廠方法模式的定義: 工廠方法模式(FACTORY METHOD)是一種常用的物件建立型設計模式,此模式的核心精神是封裝類中不變的部分,提取其中個性化善變的部分為獨立類,通過依賴注入以達到解耦