Intro設(shè)計(jì)模式中有幾個(gè)工廠模式,聊一聊這幾個(gè)工廠模式的各自用法和使用示例,工廠模式包含簡單工廠,抽象工廠,工廠方法,這些均屬于創(chuàng)建型模式, 簡單工廠首先來說一說,最簡單的簡單工廠 簡單工廠模式是由一個(gè)工廠對象決定創(chuàng)建出哪一種產(chǎn)品類的實(shí)例 嚴(yán)格的來說,簡單工廠模式是工廠模式家族中最簡單實(shí)用的模式,但不屬于23種 GOF 設(shè)計(jì)模式之一。因?yàn)槊看我略鲱愋偷臅r(shí)候必須修改工廠內(nèi)部代碼,不符合開閉原則。 來看一個(gè)例子: public class OperationFactory
{
public static Operation CreateOperation(string operate)
{
Operation operation = null;
switch (operate)
{
case "+":
operation = new OperationAdd();
break;
case "-":
operation = new OpertaionSub();
break;
case "*":
operation = new OperationMul();
break;
case "/":
operation = new OperationDiv();
break;
}
return operation;
}
}這是一個(gè)簡單的計(jì)算器的示例,支持簡單的加減乘除操作,如果要增加一個(gè)操作的話就必須要有增加一個(gè) 抽象工廠抽象工廠模式,提供一系列相關(guān)或相互依賴對象的接口,而無需指定他們具體的類。 實(shí)現(xiàn)抽象工作模式所需要的組件,主要部分:
在客戶端根據(jù)不同的配置選擇不同的工廠,例如根據(jù)配置的數(shù)據(jù)庫類型的不同選擇使用 Access 數(shù)據(jù)庫倉儲(chǔ)的工廠還是使用 SqlServer 數(shù)據(jù)庫的倉儲(chǔ)工廠 示例: IDbFactory factory = new AccessFactory(); var userRepo = factory.CreateUserRepo(); userRepo.Insert(null); var departmentRepo = factory.CreateDepartmentRepo(); factory = new SqlServerFactory(); userRepo = factory.CreateUserRepo(); userRepo.Insert(null); 工廠方法工廠方法模式(Factory Method)定義一個(gè)用于創(chuàng)建對象的接口,讓子類決定實(shí)例化哪一個(gè)類。工廠方法使一個(gè)類的實(shí)例化延遲到子類。 工廠方法模式實(shí)現(xiàn)時(shí),客戶端需要決定實(shí)例化哪一個(gè)工廠來實(shí)現(xiàn)客戶端的操作,也會(huì)存在著選擇判斷的問題,不過和簡單工廠相比,簡單工廠的選擇判斷是在工廠內(nèi)部,而工廠方法則將選擇判斷轉(zhuǎn)移到了客戶端。 示例: ILeifengFactory factory = new UndergraduteFactory(); var studentLeifeng = factory.CreateLeifeng(); studentLeifeng.BuyRice(); factory = new VolunteerFactory(); var leifeng1 = factory.CreateLeifeng(); leifeng1.Sweep(); More工廠模式的作用無外乎下面這四個(gè)。這也是判斷要不要使用工廠模式的最本質(zhì)的參考標(biāo)準(zhǔn)。
工廠方法和抽象工廠的區(qū)別工廠方法模式:定義一個(gè)用于創(chuàng)建對象的接口,讓子類決定實(shí)例化哪一個(gè)類 抽象工廠關(guān)鍵在于產(chǎn)品之間的抽象關(guān)系,所以一般至少要兩個(gè)產(chǎn)品;工廠方法在于生成產(chǎn)品,不關(guān)注產(chǎn)品間的關(guān)系,所以可以只生成一個(gè)產(chǎn)品。 抽象工廠更像一個(gè)復(fù)雜版本的策略模式,策略模式通過更換策略來改變處理方式或者結(jié)果;而抽象工廠的客戶端,通過更換工廠而改變結(jié)果。 工廠方法目的是生產(chǎn)產(chǎn)品,所以能看到產(chǎn)品,而且還要使用產(chǎn)品。當(dāng)然,如果產(chǎn)品在創(chuàng)建者內(nèi)部使用,那么工廠方法就是為了完善創(chuàng)建者,從而可以使用創(chuàng)建者。另外創(chuàng)建者本身是不能更換所生產(chǎn)產(chǎn)品的。 抽象工廠的工廠是類;工廠方法的工廠是方法。抽象工廠的工廠類就做一件事情生產(chǎn)產(chǎn)品。生產(chǎn)的產(chǎn)品給客戶端使用,絕不給自己用。工廠方法生產(chǎn)產(chǎn)品,可以給系統(tǒng)用,可以給客戶端用,也可以自己這個(gè)類使用。自己這個(gè)類除了這個(gè)工廠方法外,還可以有其他功能性的方法。 選擇的優(yōu)化簡單工廠因?yàn)檫x擇是在工廠內(nèi)部的,不符合開閉原則,抽象工廠和工廠方法是將選擇權(quán)交給客戶端,由客戶端根據(jù)需要自己決定要實(shí)例化的工廠。 使用反射+配置優(yōu)化private static readonly string AssemblyName = "AbstractFactoryPattern";
private static readonly string DbName = ConfigurationHelper.AppSetting("DbName");
public static IUserRepo CreateUserRepo()
{
return (IUserRepo)typeof(DataAccess).Assembly.CreateInstance($"{AssemblyName}.{DbName}UserRepo");
}
public static IDepartmentRepo CreateDepartmentRepo()
{
return (IDepartmentRepo)typeof(DataAccess).Assembly.CreateInstance($"{AssemblyName}.{DbName}DepartmentRepo");
}使用依賴注入依賴注入可以使得我們的代碼變得更加良好,擴(kuò)展性更強(qiáng)。 // 依賴注入 var builder = new ContainerBuilder(); builder.RegisterType<VolunteerFactory>().As<ILeifengFactory>(); builder.RegisterType<SqlServerFactory>().As<IDbFactory>(); var container = builder.Build(); var leifengFactory = container.Resolve<ILeifengFactory>(); var volunteer = leifengFactory.CreateLeifeng(); volunteer.Wash(); var dbFactory = container.Resolve<IDbFactory>(); dbFactory.CreateDepartmentRepo().CreateDepartment(null); Reference |
|
|