您好,登錄后才能下訂單哦!
這篇文章主要講解了“.Net設計模式之抽象工廠模式怎么實現”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“.Net設計模式之抽象工廠模式怎么實現”吧!
在軟件系統中,經常面臨著“一系列相互依賴的對象”的創建工作;同時,由于需求的變化,往往存在更多系列對象的創建工作。
如何應對這種變化?如何繞過常規的對象創建方法(new),提供一種“封裝機制”來避免客戶程序和這種“多系列具體對象創建工作”的緊耦合?
提供一個接口,讓該接口負責創建一系列“相關或者相互依賴的對象”,無需指定它們具體的類。
ProductA1和ProductB1是一個系列,ProductA2和ProductB2是另一個系列。ConcreteFactory1是創建系列1的工廠方法,ConcreteFactory2是創建系列2的工廠方法。客戶程序Client只依賴了AbstractFactory和AbstractProductA、AbstractProductB,也就是客戶程序不依賴于具體實現,而是只依賴與抽象類。
如果現在需要創建一個系列3運用到客戶程序,我們只需要再寫一個系列3的工廠,繼承自AbstractFactory,這個工廠提供了2個實現:
CreateProductA();
CreateProductB();
它們分別返回ProductA3(繼承自AbstractProductA)、ProductB3(繼承自AbstractProductB)。
也就是說,如果新增了系列3,Client程序可以完全不用改動,可能只需要改一些配置文件,增加一些新dll就可以應對變化。
可以看出,在抽象工廠模式的結構圖有以下角色:
(1)、抽象產品類角色(AbstractProduct):為抽象工廠中相互依賴的每種產品定義抽象接口對象,也可以這樣說,有幾種產品,就要聲明幾個抽象角色,每一個抽象產品角色和一種具體的產品相匹配。
(2)、具體產品類(ConcreteProduct):具體產品類實現了抽象產品類,是針對某個具體產品的實現的類型。
(3)、抽象工廠類角色(Abstract Factory):定義了創建一組相互依賴的產品對象的接口操作,每種操作和每種產品一一對應。
(4)、具體工廠類角色(ConcreteFactory):實現抽象類里面的所有抽象接口操作,可以創建某系列具體的產品,這些具體的產品是“抽象產品類角色”的子類。
作為長子的我,希望能有一套歐式風格的房子,再加上田園風光,此生足矣。我弟弟就不一樣了,他想要一套現代樣式的房子,如果兄弟姊妹再多年一點,那就有更多的要求了。由于房子由房頂、地板、窗戶和房門組成,其他組件暫時省略,有這么多套房子要建設,每套房子的房頂、地板、窗戶和房門都是一個體系的,那就讓我們看看如何使用【抽象工廠】模式來實現不同房屋的建造。
//抽象道路 public abstract class Road { } //抽象房屋 public abstract class Building { } //現代風格道路 public class ModernRoad : Road { } //現代風格房屋 public class ModernBuilding : Building { } //古典風格道路 public class ClassicRoad : Road { } //古典風格房屋 public class ClassicBuilding : Building { } //抽象工廠 public abstract class FacilitiesFactory { public abstract Road CreateRoad(); public abstract Building CreateBuilding(); } //現代風格 public class ModernFacilitiesFactory : FacilitiesFactory { public override Road CreateRoad() { return new ModernRoad(); } public override Building CreateBuilding() { return new ModernBuilding(); } } //古典風格 public class ClassicFacilitiesFactory : FacilitiesFactory { public override Road CreateRoad() { return new ClassicRoad(); } public override Building CreateBuilding() { return new ClassicBuilding(); } }
可以看出,客戶程序依賴的全部是抽象類,在客戶程序代碼中沒有出現過任何具體的實現類。因為在系列需要變化的時候,是不需要改變抽象類的,只是增加一個抽象類的實現而已,又由于客戶程序只依賴于抽象,所以系列變化的時候客戶程序完全無需變化。
internal class GameManager { private FacilitiesFactory facilitiesFactory; private Road road; private Building building; public GameManager(FacilitiesFactory facilitiesFactory) { this.facilitiesFactory = facilitiesFactory; } public void BuildGameFacilities() { road = facilitiesFactory.CreateRoad(); building = facilitiesFactory.CreateBuilding(); } public void Run() { Console.WriteLine(road); Console.WriteLine(building); } }
可以看出,風格由Modern改變為Classic的時候,我們封裝好的GameManager客戶程序沒有改變,這就是我們想要的結果。GameManager的邏輯非常復雜,現在它的穩定,能夠大大方便我們的工作。
GameManager g = new GameManager(new ModernFacilitiesFactory()); g.BuildGameFacilities(); g.Run();
就是在系列對象不發生系列添加的情況下,使用配置文件來進行例子中場景風格的替換。添加一個App.config文件,在其中加入風格設置的字段。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="factoryName" value="ModernFacilitiesFactory"></add> </appSettings> </configuration>
然后,在代碼中讀取這個配置字段,根據配置字段的值來做實現。首先實現一個構建方法,然后再在客戶程序中調用。
public static FacilitiesFactory GetInstance() { string factoryName = ConfigurationSettings.AppSettings["factoryName"]; FacilitiesFactory f; switch (factoryName) { case "ModernFacilitiesFactory": f = new ModernFacilitiesFactory(); break; case "ClassicFacilitiesFactory": f = new ClassicFacilitiesFactory(); break; default: f = null; break; } return f; } //客戶程序 public static void Main() { GameManager g = new GameManager(GetInstance()); g.BuildGameFacilities(); g.Run(); }
其實還有一種需求就是擴展新的系列對象,如果還是不需要對客戶程序進行維護,而僅是添加了新的系列對象的類,那將是很舒服的一件事。這樣我們就可以通過添加DLL并配合配置文件的使用,就能在不修改源程序代碼的情況下,擴展出我們需要的新的系列對象
public staticFacilitiesFactory GetInstance() { string factoryName = ConfigurationSettings.AppSettings["factoryName"]; FacilitiesFactory f; if (factoryName != "") f = (FacilitiesFactory)Assembly.Load(factoryName).CreateInstance(factoryName); else f = null; return f; }
這樣,我們在擴展時僅需將擴展的DLL放在相應的路徑下并配合配置文件即實現了我們的擴展。
如果沒有應對“多系列對象創建”的需求變化,則沒有必要使用AbstractFactory模式,這時候使用簡單的靜態工廠完全可以。
“系列對象"指的是這些對象之間有相互依賴、或作用的關系,例如游戲開發場景中“道路”與“房屋”的依賴,“道路”與“地道”的依賴。
AbstractFactory模式主要在于應對“新系列”的需求變動。其缺點在于難以應對“新對象”的需求變動。
AbstractFactory模式經常和FactoryMethod模式共同組合來應對“對象創建”的需求變化。
【抽象工廠】模式將系列產品的創建工作延遲到具體工廠的子類中,我們聲明工廠類變量的時候是使用的抽象類型,同理,我們使用產品類型也是抽象類型,這樣做就盡可能的可以減少客戶端代碼與具體產品類之間的依賴,從而降低了系統的耦合度。耦合度降低了,對于后期的維護和擴展就更有利,這也就是【抽象工廠】模式的優點所在。可能有人會說在Main方法里面(這里的代碼就是客戶端的使用方)還是會使用具體的工廠類,對的。這個其實我們通過Net的配置,把這部分移出去,最后把依賴關系放到配置文件中。如果有新的需求我們只需要修改配置文件,根本就不需要修改代碼了,讓客戶代碼更穩定。依賴關系肯定會存在,我們要做的就是降低依賴,想完全去除很難,也不現實。
有優點肯定就有缺點,因為每種模式都有他的使用范圍,或者說要解決的問題,不能解決的問題就是缺點了,其實也不能叫缺點了。【抽象工廠】模式很難支持增加新產品的變化,這是因為抽象工廠接口中已經確定了可以被創建的產品集合,如果需要添加新產品,此時就必須去修改抽象工廠的接口,這樣就涉及到抽象工廠類的以及所有子類的改變,這樣也就違背了“開發——封閉”原則。
如果系統需要多套的代碼解決方案,并且每套的代碼方案中又有很多相互關聯的產品類型,并且在系統中我們可以相互替換的使用一套產品的時候可以使用該模式,客戶端不需要依賴具體實現。
微軟的類庫發展了這么多年,設計模式在里面有大量的應用,【抽象工廠】模式在.NET類庫中也存在著大量的使用,比如和操作數據庫有關的類型,這個類就是System.Data.Common.DbProviderFactory,這個類位于System.Data.dll程序集中。該類扮演抽象工廠模式中抽象工廠的角色,DbProviderFactory就是【抽象工廠】模式UML里面AbstractFactory類型。其他具體的工廠類型繼承DbProviderFactory類型。
感謝各位的閱讀,以上就是“.Net設計模式之抽象工廠模式怎么實現”的內容了,經過本文的學習后,相信大家對.Net設計模式之抽象工廠模式怎么實現這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。