C#設計模式之建立類模式:抽象原廠模式

來源:互聯網
上載者:User

標籤:修改   隔離   機構   擴充   選擇   es2017   通過   良好的   圓形   

定義:提供一個建立一系列相關或相互依賴對象的介面,而無須指定他們具體的類。

概念

要理解抽象原廠模式,首先要瞭解幾個概念,一個是產品等級結構,另一個是產品族。

Factory 方法模式中引入了工廠等級結構,解決了簡單原廠模式中工廠類職責太重的問題,但由於Factory 方法模式中的每個具體工廠只有一個或者一組重載的Factory 方法,只能生產一種產品,可能會導致系統中存在大量的工廠類,勢必會增加系統的開銷,有時候可能需要一個工廠能夠提供多種產品對象,而不是單一的產品對象,例如海爾電器公司可以生產海爾電視、海爾冰箱、海爾洗衣機等,公司或工廠可以生產多種產品,而不是單一的某個產品。此時,可以考慮將一些相關的產品組成一個“產品族”,由同一個工廠來統一生產,這就是本章將要學習的抽象原廠模式的基本思想。為了更好的理解抽象原廠模式,先引入以下兩個概念,就是產品等級結構和產品族。

產品等級結構:產品等級結構就是產品的繼承結構,例如一個抽象類別是電視機,其子類可以是海爾電視、海信電視、小米電視,則抽象電視機與具體品牌的電視機之間構成了一個產品的等級結構,抽象電視機是父類,而具體品牌的電視機是其子類。

產品族:在抽象原廠模式中,產品族是指由同一個工廠生產的,位於不同產品等級結構中的一組產品。例如海爾電視、海爾冰箱和海爾洗衣機是同一個產品族,這個產品族由三個分屬不同的產品等級結構中,組合成了一個產品族。

產品等級結構和產品族的如下:

在,不同顏色的多個正方形、圓形和橢圓形分別構成了3個不同的產品等級結構,而顏色相同的正方形,圓形和橢圓構成了一個產品族,每一個形狀對象都位於某個產品族,並屬於某個產品等級結構,共有5個產品族,分屬於3個產品等級結構中。只要指定一個產品所處的產品族和他所屬的等級結構,就可以確定這個唯一的產品。

抽象原廠模式概述

當系統所提供的工廠生產的具體產品並不是一個簡單的額對象,而是多個位於不同產品等級結構、屬於不同類型的具體產品時就可以使用抽象原廠模式。抽象原廠模式時多有形式的原廠模式中最為抽象和最具一般性的一種形式。抽象原廠模式與Factory 方法模式最大的區別在於,Factory 方法模式針對單一的產品結構,而抽象原廠模式需要面對多個產品等級結構。當一個工廠等級結構可以建立出分屬於不同產品等級結構的一個產品族中的所有對象時,抽象原廠模式比Factory 方法模式更為簡單、更有效率。抽象原廠模式的如下:

中,每一個具體工廠都可以生產一個產品族上面的所有產品,例如顏色相同的正方形、圓形、橢圓。這些產品分屬於三個不同的產品等級結構。如果要用簡單原廠模式來做,只設計一個工廠類,在其中要寫15個建立不同產品的方法,職責過重;如果要用Factory 方法模式來寫,要分別寫15個不同的實體工廠以及三個不同的抽象工廠(Factory 方法模式是針對單一產品等級結構,所以要寫三個不同的抽象工廠代表每一個產品等級結構),系統中的類的個數成倍增加,系統開銷和複雜度都由上升;目前為止最好的辦法就是使用抽象原廠模式了,只需要建立一個針對不同產品等級結構組成的產品族的一個抽象的工廠類,以及五個分別生產不同產品族的實體工廠。可以看出抽象工廠大大的減少了系統中類的數量。下面列出上面提到的關於抽象原廠模式中的各個組成部分:

①AbstractFactory(抽象工廠):它定義了一組建立一族產品的方法,每一個方法對應一種產品。
②ConcreteFactory(具體工廠):它繼承或實現了抽象工廠,將抽象工廠定義的方法實現為自己特有的行為來產生特定的一族產品類。
③AbstractProduct(抽象產品):它為每種產品聲明介面,聲明了每種產品做具有的業務方法。
④ConcreteProduct(具體產品):定義具體的產品對象,實現或繼承抽象產品中所定義的業務方法。

為抽象原廠模式的類圖:

抽象原廠模式的實現

典型的抽象工廠的代碼

abstract class AbstractFactory{public abstract AbstractProductA CreateProductA(); //Factory 方法一public abstract AbstractProductB CreateProductB(); //Factory 方法二……}

典型的具體工廠的代碼

class ConcreteFactory1 : AbstractFactory{     //Factory 方法一public override AbstractProductA CreateProductA() {    return new ConcreteProductA1();}//Factory 方法二public override AbstractProductB CreateProductB() {    return new ConcreteProductB1();}……}
抽象工廠的應用執行個體 執行個體說明

某軟體公司要開發一套介面皮膚庫,可以對基於.NET平台的案頭軟體進行介面美化。使用者在使用時可以通過菜單來選擇皮膚,不同的皮膚將提供視覺效果不同的按鈕、文字框、組合框等介面元素,例如春天(Spring)風格的皮膚將提供淺綠色的按鈕、綠色邊框的文字框和綠色邊框的組合框,而夏天(Summer)風格的皮膚則提供淺藍色的按鈕、藍色邊框的文字框和藍色邊框的組合框,其結構如所示:

該皮膚庫需要具備良好的靈活性和可擴充性,使用者可以自由選擇不同的皮膚,開發人員可以在不修改既有代碼的基礎上增加新的皮膚。
現使用抽象原廠模式來設計該介面皮膚庫。

執行個體類圖

通過分析,本執行個體的機構圖如下:

中,SkinFactory充當抽象介面,其子類SpingSkinFactory和SummerSkinFactory充當具體工廠,介面Button、TextField、ComboBox充當抽象產品,其子類SpringButtong、SpingTextField等充當具體產品。

執行個體代碼

①Button:按鈕介面,充當抽象產品

interface Button    {        void Display();    }

②SpringButton:SpringButton按鈕類,充當具體產品

class SpringButton : Button     {        public void Display()         {            Console.WriteLine("顯示淺綠色按鈕。");        }    }

③SummerButton:充當具體產品

 class SummerButton : Button     {        public void Display()         {           Console.WriteLine("顯示淺藍色按鈕。");        }        }

④TextField:文字框介面,充當抽象產品

interface TextField    {        void Display();    }

⑤SpringTextField:具體產品

 class SpringTextField : TextField     {        public void Display()         {            Console.WriteLine("顯示綠色邊框文字框。");        }    }

⑥SummerTextField:具體類

 class SummerTextField : TextField     {        public void Display()         {            Console.WriteLine("顯示藍色邊框文字框。");        }        }

⑦ComboBox:抽象產品

 interface ComboBox    {        void Display();    }

⑧SpringComboBox:具體產品

class SpringComboBox : ComboBox     {        public void Display()         {            Console.WriteLine("顯示綠色邊框組合框。");        }    }

⑨SummerComboBox:具體產品

class SummerComboBox : ComboBox     {        public void Display()         {            Console.WriteLine("顯示藍色邊框組合框。");        }        }

⑩SkinFactory:介面皮膚工廠介面,充當抽象工廠

interface SkinFactory    {        Button CreateButton();        TextField CreateTextField();        ComboBox CreateComboBox();    }

(11)SpringSkinFactory:具體的皮膚工廠

class SpringSkinFactory : SkinFactory     {        public Button CreateButton()         {            return new SpringButton();        }        public TextField CreateTextField()         {            return new SpringTextField();        }        public ComboBox CreateComboBox()         {            return new SpringComboBox();        }    }

(12)SummerSkinFactory:具體的皮膚工廠

class SummerSkinFactory : SkinFactory     {        public Button CreateButton()         {            return new SummerButton();        }        public TextField CreateTextField()         {            return new SummerTextField();        }        public ComboBox CreateComboBox()         {            return new SummerComboBox();        }    }

(13)用戶端調用:

static void Main(string[] args)        {            //使用抽象層定義            SkinFactory factory;            Button bt;            TextField tf;            ComboBox cb;            //讀取設定檔            string factoryType = ConfigurationManager.AppSettings["factory"];            //反射產生對象            factory = (SkinFactory)Assembly.Load("AbstractFactorySample").CreateInstance(factoryType);            bt = factory.CreateButton();            tf = factory.CreateTextField();            cb = factory.CreateComboBox();            bt.Display();            tf.Display();            cb.Display();            Console.Read();        }

用戶端調用還是使用設定檔和反射來做一些符合開閉原則的收尾工作。在這個系統中,如果要更換皮膚介面,只需要修改設定檔就可以了。

開閉原則的傾斜性

上面執行個體其實存在一個很嚴重的問題,那就是如果在設計之初忽略了一些細節,在後面要進行擴充時會非常困難,比如我們現在要增加一個選項按鈕框,由於在抽象工廠類中已經將規則寫死,要想增加選項按鈕框,如果在Factory 方法模式中的話直接新增抽象產品類+具體產品類+抽象工廠+具體工廠來對系統進行擴充即可,符合開閉原則,而在抽象原廠模式中是不能這樣做的,因為抽象工廠類中的邏輯已經寫死,在這個例子中,抽象工廠類只定義了Button CreateButton();TextField CreateTextField();ComboBox CreateComboBox();這三個方法,如果新增選項按鈕,那麼必須對源碼進行修改,違反了開閉原則。

在抽象原廠模式中,新增產品族很方便,直接新增一個具體工廠和一族具體產品即可,但是如果新增產品等級結構,則會很麻煩,需要對源碼進行修改,這樣就違反了開閉原則。

抽象原廠模式的優缺點和適用環境

抽象原廠模式是Factory 方法模式的進一步的延伸,由於它提供了功能更為強大的工廠類並具備較好的可擴充性,在軟體開發中廣泛的得到了應用,尤其在一些架構和類庫中。它是最常用的設計模式之一。

抽象原廠模式優點

①隔離了具體類的產生,使得用戶端並不需要知道什麼被建立
②當一個產品族中的多個對象被設計成一起工作時,它能夠保證用戶端始終只使用同一個產品族中的對象
③增加新的產品族很方便,無須修改已有系統,符合開閉原則

抽象原廠模式缺點

增加新的產品等級結構麻煩,需要對原有系統進行較大的修改,甚至需要修改抽象層代碼,這顯然會帶來較大的不便,違背了開閉原則

抽象原廠模式適用環境

①一個系統不應當依賴於產品類執行個體如何被建立、組合和表達的細節
②系統中有多於一個的產品族,但每次只使用其中某一產品族
③屬於同一個產品族的產品將在一起使用,這一約束必須在系統的設計中體現出來
④產品等級結構穩定,設計完成之後,不會向系統中增加新的產品等級結構或者刪除已有的產品等級結構

 

C#設計模式之建立類模式:抽象原廠模式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.