提及軟件架構中的設計模式,大多數人確定第一句就是,工廠模式。準確講經典24個設計模式中沒有工廠模式,而是簡單工廠模式,工廠方法模式和抽象工廠模式這三種,三種互相有本質區別,各自爲解決不一樣領域的問題,而造成的一套代碼體系。我記得我畢業後第一份工做跳槽的時候,遇到的一次面試就有設計模式題目,不過當時太嫩,大敗而歸,也是那時知道有設計模式這個東東,由於這個學校是不教的。今後也就對設計模式就開始去研究啦,因而就有了這個系列的文章。面試
面向對象編程的三大基本特性:封裝、繼承、多態。簡簡單單的概念,其實每個特性都能拓展得很深很深。這裏咱們只看下多態,多態就是利用了繼承的概念,抽象依賴實現,能夠看一個你們在學習編程語言啓蒙的時候都會遇到的一個實例,首先建立一個基類,用接口也能夠,裏面放一個方法。編程
建立SampleBase類,代碼以下:後端
1 public class SampleBase { 2 3 public String getName() 4 { 5 return this.getClass().toString(); 6 } 7 }
再建立一個集成該類的衍生類,代碼以下:設計模式
1 public class SampleImpl extends SampleBase { 2 @Override 3 public String getName() 4 { 5 return this.getClass().toString(); 6 } 7 }
在測試類中進行測試,測試代碼以下:架構
public static void main(String[] args) { SampleBase base = new SampleImpl(); System.out.println(base.getName()); }
運行結果:編程語言
class com.aspnetdream.test.SampleImpl
其實對於這個狀況,我腦海中一直記得一句話,基類指針指向子類應用,個人學習生涯接觸這個最開始是在C++的語言中學習的,記住這句話,應對繼承和多態我以爲是萬能的法寶。基於編程語言這麼一個優秀的特質,再想一想在工做中遇到的不少應用場景,我曾經開發一個餐飲的ERP系統,在處理訂單的時候,不少不一樣的單據,這些單據有相通之處,也會有各自不一樣點,好比配料訂單和退貨訂單,這兩種訂單,相同的地方是對業務單據的物料拆分處理是同樣的,但最後訂單存儲的表是不同的,也就是說,兩個單據我在拆分處理須要同樣的代碼,但在這一步完成以後,又各自走向不一樣的代碼,好,套用簡單工廠模式來解決。ide
建立單據基類IOrderInfo,我在這裏把他定義成了一個接口,實際應用中能夠定義爲抽象類,甚至就是一個類。
建立IOrderInfo 接口,代碼以下:學習
1 //簡單工廠模式接口定義層 2 public interface IOrderInfo { 3 public String getOrderInfo(); 4 }
窗建完接口,咱們分別建立配料單和退貨單的衍生類。
配料單類OrderMakeCustom,代碼以下:測試
1 //簡單工程接口實現層 消耗訂單操做類 2 public class OrderMakeCustom implements IOrderInfo { 3 4 public String getOrderInfo() 5 { 6 return this.getClass().toString(); 7 } 8 9 }
退貨單類 OrderReturnCustom,代碼以下:this
//簡單工廠接口實現層 退貨訂單操做類 public class OrderReturnCustom implements IOrderInfo { public String getOrderInfo() { return this.getClass().toString(); } }
兩個衍生類都實現IOrderInfo接口,寫到這裏稍微有經驗點的同窗就能夠看出來,在實際代碼調用中就能夠
IOrderInfo order = new OrderMakeCustom();
不錯能夠這麼作,這是比較粗暴的作法,但現實在項目開發的時候,這樣的代碼卻比比皆是。
咱們這裏使用簡單工廠來實現,把new的任務交給工廠來完成,將new的任務交給工廠而不是在具體的業務流程代碼中去完成,我我的任務有一下幾點好處:
一、代碼的整潔度,易於維護,若是整篇代碼摻雜不少的new,我想讀代碼的人是至關痛苦的,這種流線型的代碼方式,帶來的惡果就是,業務一複雜,你們就開始走迷宮。
二、將代碼放入工廠中,能夠爲後續代碼升級作準備,若是,我將對應的接口實現的全部子類對應的放入一個xml文件中,用反射來實例化一個具體的基類的,這是否是就是IOC的原型啦。
繼續代碼,建立一個Factory,在這個類中就是根據不一樣業務流程,建立不一樣訂單實例交給調用方,實現代碼:
1 public class Factory { 2 3 //簡單工廠模式 建立實現操做類工廠 4 public static IOrderInfo createOrderInfo(EServiceType createType) 5 { 6 switch(createType) 7 { 8 case Make: 9 return new OrderMakeCustom(); 10 case Return: 11 return new OrderReturnCustom(); 12 default: 13 return null; 14 15 } 16 } 17 }
爲了便於建立我這裏放了一個枚舉類型,簡單工廠的工廠類根據傳入的不一樣枚舉類型,闖將不一樣的實例類。
OK,到這裏一個簡單工廠模式就搭建完成了,咱們來測試運行,測試代碼以下:
1 public static void main(String[] args) { 2 3 SampleBase base = new SampleImpl(); 4 System.out.println(base.getName()); 5 6 //根據不一樣的類型實例化不一樣的訂單操做類 7 //------簡單工廠模式(靜態工廠模式) 8 //退貨訂單操做類 9 IOrderInfo order = Factory.createOrderInfo(EServiceType.Return); 10 //獲取訂單後,處理訂單 11 getOrderInfo(order); 12 13 order = Factory.createOrderInfo(EServiceType.Make); 14 getOrderInfo(order); 15 16 } 17 18 //實際項目中對訂單模型進行操做,而不用關注是那種類型訂單,在業務實現層去關注返回什麼樣的訂單 19 private static void getOrderInfo(IOrderInfo order) 20 { 21 System.out.println(order.getOrderInfo()); 22 }
運行結果:
class com.aspnetdream.bussinessImpl.OrderReturnCustom class com.aspnetdream.bussinessImpl.OrderMakeCustom
使用抽象層IOrderInfo對象做爲句柄,具體實現看不一樣的業務要求去工廠請求相應的實現層。再回到我最開始描述的場景,對兩種單據中相同的業務咱們能夠放入抽象層,甚至在抽象層咱們能夠定義不一樣的業務代碼相同的調用方法,這樣你的代碼檔次就會被拉高不少不少!簡單工廠模式也叫靜態工廠模式,它建立實現層的方式較爲呆板,只是把new的代碼都放入了工廠中,但你依然須要使用選擇模式,也就是告訴工廠你是建立A,仍是建立B,這就是我代碼中加入枚舉的緣由了,這其實在代碼本質上和new 一個具體實現沒有太大的區別。因此,由此就產生了工廠方法模式。對於這個模式的應用在個人印象中是基於不一樣的產品操做而想到的,在開發一個POS後端應用時,都是產品信息,可是交給POS端和交給手機移動端的信息是不同的,POS端也許信息比較全面,交給移動端信息比較少,由於在我這個產品中,移動端僅限於看報表。這裏咱們嘗試着用工廠方法模式來解決這個問題。
首先建立產品的基類,iproduct接口,代碼以下:
1 //工廠方法模式---抽象角色接口 2 public interface iproduct { 3 4 public String getPrdName(); 5 }
再分別建立Pos和移動端不一樣的產品實現類,PosProduct和MobileProduct類,代碼實現:
//工廠方法模式 具體角色類 public class MobileProduct implements iproduct { //實現抽象角色接口 @Override public String getPrdName() { return this.getClass().toString(); } } //工廠方法模式---具體角色類 public class PosProduct implements iproduct { @Override public String getPrdName() { return this.getClass().toString(); } }
基於應用角色咱們就建立完了,使用工廠模式,確定須要建立工廠嘛,建立產品抽象工廠IProductFactory,代碼以下:
//工廠方法模式 ---- 抽象工廠 public abstract class IProductFactory { public abstract iproduct getProduct(); }
抽象工廠負責返回抽象角色,抽象對抽象。
有抽象就有實現,咱們須要操做POS和Mobile端不一樣的產品信息,如是,針對抽象咱們有2個不一樣業務實現要求,那麼實現抽象來建立這2個實現工廠PosFactory和MobileFactory,代碼以下:
1 //工廠方法模式 ----具體角色工廠 pos產品工廠 2 public class PosFactory extends IProductFactory { 3 4 public iproduct getProduct() 5 { 6 return new PosProduct(); 7 } 8 9 } 10 11 12 //工廠方法模式---工廠方法模式 具體產品共 移動類產品工廠類 13 public class MobileFactory extends IProductFactory { 14 15 public iproduct getProduct() 16 { 17 return new MobileProduct(); 18 } 19 20 }
建立完這一步其實基本的工廠方法模式也就完成了,接下來咱們測試,測試代碼以下:
1 public static void main(String[] args) { 2 3 //------工廠方法模式 4 IProductFactory ifactory = new MobileFactory();//移動端類產品工廠 返回移動端產品 5 iproduct prd= ifactory.getProduct(); 6 System.out.println(prd.getPrdName()); 7 8 ifactory = new PosFactory();//返回pos類產品工廠 返回pos類產品 9 prd = ifactory.getProduct(); 10 System.out.println(prd.getPrdName()); 11 12 } 13 14 //實際項目中對訂單模型進行操做,而不用關注是那種類型訂單,在業務實現層去關注返回什麼樣的訂單 15 private static void getOrderInfo(IOrderInfo order) 16 { 17 System.out.println(order.getOrderInfo()); 18 }
運行結果:
class com.aspnetdream.driver.productImpl.MobileProduct class com.aspnetdream.driver.productImpl.PosProduct
工廠方法模式,在個人記憶中就是抽象對抽象,實現對實現,實現多少依據具體的業務需求來完成,能夠無限的實現下去,固然,你就須要無限的工廠來幫你實現。
簡單工廠模式和工廠方法模式比較分析:
在我看來,簡單工廠模式就是工廠模式中的屌絲,工廠方法模式就是高富帥,屌絲的最大特色就是,「躲進小樓成一統,管他春夏與秋冬」,外部怎麼弄的我無論,你給讓我建立什麼類型,我建立好給你就行,同時你也必須將須要建立的類型寫入工廠中,也就是new一個實例。
然而,高富帥的工廠方法模式,有娘生也有娘養,首先在工廠的抽象層,你就必需要對應你這個工廠操做的對應的角色類型,也就是說你一出生屬於哪一個幫派的已經基本肯定了,因此通常都會對角色進行抽象,在工廠抽象層操做的類型確定也是抽象,「抽象對抽象」---又說了一遍。
基於上面的表述,簡單工廠模式路子很野,你想建立啥我就建立啥,隨便來,這和直線的代碼比起來其實差異不大。工廠方法模式一脈相承,代碼比簡單工廠模式要複雜,可是無形中確規範了很多,依據這樣的模式,代碼分層其實就特別順溜。
好了,對應於工廠模式我剛纔說了,你想實現多少就實現多少,這是好處,也是壞處,代碼總歸是有限的,需求氾濫,也總過就人死燈滅的時候,正是因爲實現終歸是有限的,因此在實現的時候,若是能不要這麼多實現工廠是否是代碼就稍微簡潔點呢。由此,咱們就產生了抽象工廠模式,將原先在工廠方法模式中,實現工廠的代碼移到一個統一的抽象層中,再來針對抽象進行實現,看看代碼怎麼實現。
建立抽象工廠模式的抽象工廠類AbstractFactory,代碼以下:
1 //抽象工廠模式--抽象工廠 2 public abstract class AbstractFactory { 3 4 public abstract iproduct createPosProdct(); 5 6 public abstract iproduct createMobileProduct(); 7 }
針對抽象類的實現層DefaultFactroy,代碼以下:
1 //抽象工廠模式的工廠實現層 2 public class DefaultFactory extends AbstractFactory{ 3 4 public iproduct createPosProdct() 5 { 6 return new PosProduct(); 7 } 8 9 public iproduct createMobileProduct() 10 { 11 return new MobileProduct(); 12 } 13 }
好,抽象工廠就塑造好了,下面測試,測試代碼以下:
1 public static void main(String[] args) { 2 3 ///---抽象工廠模式 4 AbstractFactory dfactory = new DefaultFactory(); 5 prd = dfactory.createMobileProduct(); 6 System.out.println(prd.getPrdName()); 7 8 prd = dfactory.createPosProdct(); 9 System.out.println(prd.getPrdName()); 10 }
運行結果:
class com.aspnetdream.driver.productImpl.MobileProduct class com.aspnetdream.driver.productImpl.PosProduct
抽象工廠和工廠方法模式我以爲沒有誰好誰壞,不一樣的應用場景使用不一樣的模式,在咱們現實的工做場景中,處理一個問題,每每是幾種模式一塊兒用,某個應用模式的內部代碼或許有其餘的模式來實現。二十四種設計模式,其實每個割裂開來看,每一個都很簡單,上面的代碼相信每個人都能看的懂,但,如何去用就是基本功的問題,代碼靈活地拓展和應用也一樣是對自身代碼能力的一個要求。
好了,就此擱筆,算是拋磚引玉,歡迎拍磚指教!
個人目錄結構: