設計模式--------工廠模式html
設計模式--------設計原則設計模式
兩個月前寫過一次設計模式系列,但很不滿意就刪除了。顯然但願能作到學以至用,而非看書總結,設計模式絕對是你解決問題的一個思路,但在這有點本身的小建議,設計模式ide
並非用做提升你代碼的效率,用它的目的只是讓你的代碼看起來更規範,更易擴展與維護。因此有的時候你站在你自身須要去選擇要不要使用設計模式。上週工做當中有一個需求ui
正好是適合用工廠模式來解決的,因此就在這給你們討論討論工廠模式吧。this
在工廠模式中,咱們在建立對象時不會對客戶端暴露建立邏輯,而且是經過使用一個共同的接口來指向新建立的對象。spa
好比說,我要給其餘終端提供保存實例的接口,可是實例卻用不少個,這時提供的接口,若是每一個實例都提供一邊,就會變成這樣提供多個端口,若是要增長就要繼續提供接口,故設計
此我就想到了用工廠模式。code
就比如中午你下樓去吃飯,別人問你幹啥去?你說我去吃黃燜雞,我去吃燴麪,我去吃肯德基,去吃麻辣燙。。。。這些好像沒錯,可是估計你不會這麼回答,你通常都是回答orm
我去吃飯。這就是工廠模式要走的,具體你要吃什麼東西,不用告訴別人,別人問的主題是你去幹什麼,你告訴他你娶吃飯就行,具體你要吃什麼,是你本身的決定,無需說出來。htm
優勢: 一、一個調用者想建立一個對象,只要知道其名稱就能夠了。
二、擴展性高,若是想增長一個產品,只要擴展一個工廠類就能夠。
三、屏蔽產品的具體實現,調用者只關心產品的接口。
缺點:每次增長一個產品時,都須要增長一個具體類和對象實現工廠,使得系統中類的個數成倍增長,在必定程度上增長了系統的複雜度,同時也增長了系統具體類的依賴。這
並非什麼好事。
組成部分:
工廠類角色:這是本模式的核心,在此它會根據不一樣的產品選擇生產什麼東西。
抽象產品角色:它通常是具體產品繼承的父類或者實現的接口。由接口或者抽象類來實現。
具體產品角色:工廠類所建立的對象就是此角色的實例。
首先定義一個接口(抽象產品角色):
public interface ISaveACDb { void SaveACDB(); }
根據產品定義各自的類(具體產品類)
public class SaveACDDbToBuChong : ISaveACDb { public bool SaveACDB() { return true; } } public class SaveACDDbToArchivesCases : ISaveACDb { public bool SaveACDB() { return true; } }
接口工廠類的定義:
public class SaveACDb_Factory { public static ISaveACDb Create_SaveACDb_Factory(string type) { ISaveACDb save = null; switch (type) { case "ArchivesCases": save = new SaveACDDbToArchivesCases(); break; case "BuChong": save = new SaveACDDbToBuChong(); break; } return save; } }
調用代碼:
public class WinformClientDbController : Controller { [HttpPost] public void SaveACInfo(string type) { var result = SaveACDb_Factory.Create_SaveACDb_Factory(type); result.SaveACDB(); } }
問:若是一直增長產品,是否是就要增長產品類?
答:是的。
有沒有發現問題,這樣不斷增長產品,而後增長產品類到時沒什麼,可是相應的回去修改工廠類,有沒有發現,那麼這樣就有問題,就像我上篇設計模式提到的「開閉原則」,咱們在
這種模式下就充分的違背了,因此若是產品類若是會大量增長的話,你最起碼要知道這是違背設計原則的。
問:那該怎麼解決呢?
答:用反射。
反設我已經在基礎拾遺------反射詳解介紹過來。
簡單工廠中使用反射的目的就是去掉工廠類中的switch(或if)。ps:想想這一改變,特別是我如今這種給其餘客戶端提供接口的程序,大大第提升代碼的解耦。
代碼以下:
public class SaveACDb_Factory { public static ISaveACDb Create_SaveACDb_Factory(string obj, string className) { Assembly assembly = Assembly.GetExecutingAssembly(); // 獲取當前程序集 var result = (ISaveACDb)assembly.CreateInstance("StrokeLocalWinformInterface" + ".SaveACDDbTo" + className); return result; } }
調用
[HttpPost] public void SaveACInfo(string obj, string userNickeName, string userToken, string className) { if (1 > 2)//驗證usertoken return; var result = SaveACDb_Factory.Create_SaveACDb_Factory(obj, className); result.SaveACDB(obj); }
就像上面說的,若是咱們的產品不斷增長且成樹裝結構增長,咱們就要說說抽象工廠。
若是別人爲你幹啥去,你說你去吃飯去,可是你再去的過程中,若是考慮肯德基要吃雞翅仍是漢堡,他們都是什麼口味,去吃快餐都是有什麼。。。。這樣若是選擇一次吃
飯,是否是要想半個小時,因此去吃燴麪這個產品也能夠把它看成吃飯這個超級工廠的子工廠。
抽象工廠就是圍繞這超級工廠創建的其餘工廠。超級工廠是其餘工廠的工廠。
優勢:當一個產品族中的多個對象被設計成一塊兒工做時,它能保證客戶端始終只使用同一個產品族中的對象。
缺點:產品族擴展很是困難,要增長一個系列的某一產品,既要在抽象的 Creator 里加代碼,又要在具體的裏面加代碼。
抽象工廠角色: 這是工廠方法模式的核心,它與應用程序無關。是具體工廠角色必須實現的接口或者必須繼承的父類。
具體工廠角色:它含有和具體業務邏輯有關的代碼。由應用程序調用以建立對應的具體產品的對象。
抽象產品角色:它是具體產品繼承的父類或者是實現的接口。
具體產品角色:具體工廠角色所建立的對象就是此角色的實例。
如下案例爲借鑑過來的,就是公司老闆有不少車,司機開車是一個超級工廠,每輛車是具體操做是另一個工廠,此次偷個懶就不本身寫案例啦。
抽象產品:就是定一個車的類,此類有一個司機開車的方法抽象方法,和具體是什麼車,進行賦值的方法。
abstract class Car{ private String name; public abstract void drive(); public String getName() { return name; } public void setName(String name) { this.name = name; } }
public interface Fruit { } public interface Veggie {
具體產品:繼承抽象產品,寶馬和奔馳都是不一樣的車。
class Benz :Car{ public void drive(){ // } } class Bmw :Car{ public void drive(){
//
} }
public class NorthernFruit implements Fruit { private String name; public NorthernFruit(String name) { } public String getName() { return name; } public void setName(String name) { this. name = name; } } public class TropicalFruit implements Fruit { private String name; public TropicalFruit(String name) { } public String getName() { return name; } public void setName(String name) { this. name = name; } } public class NorthernVeggie implements Veggie { private String name; public NorthernVeggie(String name) { } public String getName() { return name; } public void setName(String name) { this. name = name; } } public class TropicalVeggie implements Veggie { private String name; public TropicalVeggie(String name) { } public String getName() { return name; } public void setName(String name) { this. name = name; }
抽象工廠:司機就是要開車嗎。這個工廠抽象司機開車。
abstract class Driver{ public abstract Car createCar(String car) throws Exception; }
public interface Gardener { public Fruit createFruit(String name); public Veggie createVeggie(String name);
具體工廠:開寶馬和奔馳仍是不同的,這個工廠針對不一樣的車去實例。
class BenzDriver :Driver{ public Car createCar(String car) throws Exception { return new Benz(); } } class BmwDriver :Driver{ public Car createCar(String car) throws Exception { return new Bmw(); } }
public class NorthernGardener implements Gardener { public Fruit createFruit(String name) { return new NorthernFruit(name); } public Veggie createVeggie(String name) { return new NorthernVeggie(name); } } public class TropicalGardener implements Gardener { public Fruit createFruit(String name) { return new TropicalFruit(name); } public Veggie createVeggie(String name) { return new TropicalVeggie(name); } }
以上就是抽象工廠的組成部分,客戶端只需在實例化相應的工廠調用便可。
調用代碼:
//老闆 public class Boss{ public static void main(String[] args) throws Exception { Driver d = new BenzDriver(); Car c = d.createCar("benz"); c.setName("benz"); c.drive(); } }