设计模式之四(抽象工厂模式第三回合)
前言
抽象工廠模式:提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無需指定它們具體的類。
抽象工廠模式最大的好處便是易于交換產(chǎn)品系列,由于具體工廠類,例如IFactory factory=new AccessFactory(),在一個應(yīng)用中只需要在初始化的時候出現(xiàn)一次,這就使得改變一個應(yīng)用的具體工廠變得非常容易,它只需要改變具體工廠即可使用不同的產(chǎn)品配置。我們的設(shè)計不能去防止需要的變更,那么我們的理想便是讓改動變得最小,那么現(xiàn)在如果你要更改數(shù)據(jù)庫訪問,我們只需要更改具體工廠就可以做到。
第二大好處是,它讓具體的創(chuàng)建實(shí)例過程與客戶端分離,客戶端是通過他們的抽象接口操縱實(shí)例,產(chǎn)品的具體類名也被具體工廠的實(shí)現(xiàn)而分離,不會出現(xiàn)在客戶代碼中。
?
實(shí)際上,我們第二回合中的代碼中,客戶端所認(rèn)識的只有IUser和IDepartment,至于它是用Sql Server來實(shí)現(xiàn)還是Access來實(shí)現(xiàn)就不知道了。
但是接下來的問題是,如果我們再添加一個項目表Project,該怎么辦?
首先要增加三個類,IProject,SqlServerProject,AccessProject,還需要更改IFactory、以及SqlServerFactory和AccessFactory才可以實(shí)現(xiàn)。
用簡單工廠來改進(jìn)抽象工廠
現(xiàn)在我們要對上面的關(guān)系代碼進(jìn)行整改,需要前面的簡單工廠模式。http://www.cnblogs.com/aehyok/archive/2013/05/10/3072008.html
public class DataAccess {private static readonly string db="SqlServer";//private static readonly string db="Access";public static IUser CreateUser(){IUser result=null;switch(db){case"SqlServer":result=new SqlServerUser();break;case"Access":result=new AccessUser();break; }return result;}public static IDepartment CreateDepartment(){IDepartment result=null;switch(db){case"SqlServer":result=new SqlServerDepartment();break;case"Access":result=new AccessDepartment();break;}return result;} }原先一個接口,兩個接口的實(shí)現(xiàn),現(xiàn)在我們用一個DataAccess類就可以來代替了。
客戶端調(diào)用方法也有所改動
public class Test {public static void Main(){User user=new User();Console.WriteLine("調(diào)用開始");IUser iu=DataAccess.CreateUser();iu.Insert(user);iu.GetUser(1);Console.ReadLine();} }現(xiàn)在選擇那個數(shù)據(jù)庫是在DataAccess中定義的?private static readonly string? db="SqlServer";
當(dāng)然更好的辦法實(shí)在配置文件中進(jìn)行變動就可以了。
如果如前言中所說 ,添加一個項目,那么我們只需要在DataAccess類中添加雷同的方法即可。
但是還是有問題,前面我們也稍微提到過,比如現(xiàn)在有需求要用Oracle數(shù)據(jù)庫。原來只需要增加OracleFactory工廠就可以了,現(xiàn)在就比較麻煩了。
反射+抽象工廠的數(shù)據(jù)訪問程序
?如果你還不太了解反射,那么可以簡單的看一下我之前的一篇入門的反射博文http://www.cnblogs.com/aehyok/archive/2013/03/25/2963287.html
首先使用反射我們需要引用using System.Reflection來引用Reflection,就可以使用反射來優(yōu)化抽象工廠模式的先天不足。
順便來看一下反射的簡單使用,來獲得實(shí)例的方法
IUser result = new SqlServerUser(); ///這是常規(guī)的寫法接下來看看用反射的寫法,別忘了首先要引用哦
IUser result = (IUser)Assembly.Load("程序集的名稱").CreateInstance("命名空間.要實(shí)例化的類名");那么現(xiàn)在可以發(fā)現(xiàn)用了反射我們可以利用字符串來實(shí)例化對象,而變量是可以替換的,而常規(guī)的寫法都是寫死在程序里的。
接下來看看我們用反射優(yōu)化后的抽象工廠,其實(shí)也就是對上面DataAccess類進(jìn)行的優(yōu)化。
其實(shí)這里我們還可以簡單的優(yōu)化一下,就是用配置文件
<?xml version="1.0"?> <configuration><appSettings><!--<add key="DB" value="SqlServer"/>--><add key="DB" value="Access"/></appSettings> <startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup></configuration> public class DataAccess{private static readonly string db = ConfigurationManager.AppSettings["DB"];private static readonly string AssemblyName = "AbstractFactory";public static IUser CreateUser(){string ClassName = AssemblyName+"."+db+"User";IUser result = (IUser)Assembly.Load("程序集的名稱").CreateInstance("命名空間.要實(shí)例化的類名");return (IUser)Assembly.Load(AssemblyName).CreateInstance(ClassName);}public static IDepartment CreateDepartment(){string ClassName ="AssemblyName"+ "."+db+"Department";return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(ClassName);}}這樣需要什么數(shù)據(jù)庫,只需要在配置文件當(dāng)中進(jìn)行配置即可。
所以,所有在用簡單工廠的地方,都可以考慮用反射來去除switch或if,接觸分支判斷帶來的耦合。
總結(jié)
?原來通過抽象工廠可以學(xué)到這么多的知識很好,要多多吸收才可以。
最終版本的抽象工廠模式實(shí)例代碼下載鏈接為http://url.cn/GgWA2K
?
總結(jié)
以上是生活随笔為你收集整理的设计模式之四(抽象工厂模式第三回合)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HDUOJ-----4510 小Q系列故
- 下一篇: 在ExtJS的ComboBox组件中实现