官方定義:設計模式(Design Pattern)是一套被反覆使用、多數人知曉的、通過分類編目的代碼設計經驗總結。java
使用意義:使用設計模式是爲了可重用代碼,讓代碼更容易被他人理解,保證代碼的可靠性。可複用的面向對象軟件系統主要包含兩大類:應用程序工具箱和框架(框架是指構成一類特定軟件可複用設計的一組相互協做的類)。設計模式有助於對框架的理解,成熟的框架一般使用了多種設計模式,若是你能熟悉這些設計模式,毫無疑問,將能迅速的掌握框架的結構。數據庫
工廠模式將客戶類與工廠類分開,消費者在任什麼時候候須要某種產品只須要向工廠請求,消費者無須修改就能接納新產品。缺點:產品修改時,工廠類也要作相應的修改。工廠模式是編程過程當中最經常使用的設計模式,由於工廠模式至關於建立實例對象的new, 例如 A a = new A();工廠類也是用來建立實例對象的,那麼,new關鍵字能夠建立對象,爲何還要用工廠類建立實例對象呢?因爲建立實例時一般伴隨有初始化工做,若是隻是簡單的賦值操做,咱們可使用帶參數的構造方法,但若是初始化不只僅是賦值這樣簡單的操做,還包含一些邏輯判斷等大片斷的代碼,若是都寫進構造函數,會使咱們的代碼看起來很臃腫,將多個功能放進一個方法,就像將不少雞蛋放進一個籃子裏,這很危險,而且有悖於咱們面向對象的設計原則。這時須要咱們將長片斷的代碼進行分割,再封裝,之後若是須要修改,只須要修改部分片斷,而不會出現牽一動百的情形。編程
簡單工廠模式的是想源於java中的接口,經過使用接口能夠實現不相關類的相同行爲,而不須要考慮這些類的層次關係,接口就是實現類對外的外觀。主要使用在業務比較簡單的狀況下,由三種角色構成。設計模式
Client與具體實現Impl之間並沒有瓜葛,客戶端經過Factory獲取須要的接口對象,而後調用接口的方法來實現具體的功能。下面舉個例子,經過不一樣的通信工具來通訊,QQ和微信分別實現了API接口。微信
/** * 簡單工廠模式 * Created by xian.juanjuan on 2017-7-13 14:07. */ public class SimpleFactory { //根據條件建立具體的實現對象 public static MessageApi createMessageApi(int condition){ MessageApi messageApi = null; if (condition == 1){ messageApi = new QQMessageImpl(); } else if (condition == 2){ messageApi = new WeChatMessageImpl(); } return messageApi; } } class Client{ public static void main(String[] args){ //經過簡單工廠獲取接口對象 MessageApi messageApi = SimpleFactory.createMessageApi(1); messageApi.sendMessage("測試簡單工廠模式"); } } /** * 通訊接口能夠經過簡單工廠來建立 */ interface MessageApi{ //具體的功能方法 void sendMessage(String msg); } /** * 接口的具體實現--QQ通訊 */ class QQMessageImpl implements MessageApi{ @Override public void sendMessage(String msg) { System.out.println("經過QQ聊天工具發送消息:"+msg); } } /** * 接口的具體實現--微信通訊 */ class WeChatMessageImpl implements MessageApi{ @Override public void sendMessage(String msg) { System.out.println("經過微信聊天工具發送消息"+msg); } }問題1:這裏若是再增長一種通信方式(Email)時,就須要修改工廠類,顯然簡單工廠方式不能知足OCP設計原則。
問題2:客戶端在調用工廠時,須要傳入選擇的參數,這就說明客戶端必須知道每一個參數的含義,也須要知道每一個參數對應的功能處理,在必定程度上向客戶端暴露了內部實現細節。框架
每次增長一個實現類就要就要修改工廠類的實現,一般用配置文件類解決這個問題。less
建立FactoryTest.properties配置文件,內容以下,若是新增實現類,只須要修改下面的配置文件便可。ide
ImplClass=com.xianjj.pattern.QQMessageImpl
工廠類以下函數
public class SimpleFactory { public static MessageApi createMessageApi(){ Properties properties = new Properties(); InputStream inputStream; try { inputStream = SimpleFactory.class.getResourceAsStream("FactoryTest.properties"); properties.load(inputStream); } catch (IOException e) { System.out.println("加載工廠配置文件異常"); e.printStackTrace(); } //用反射建立對象 MessageApi messageApi = null; try { messageApi = (MessageApi)Class.forName(properties.getProperty("ImplClass")).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return messageApi; } }
簡單工廠一般不用建立簡單工廠類的類實例,所以,能夠把簡單工廠類看作一個工具類,直接使用靜態方法就能夠了,因此被稱做靜態工廠。爲了防止客戶端無謂的建立簡單工廠實例,能夠把簡單工廠的構造方法私有化。工具
爲了解決簡單工廠模式最大的缺點—不徹底知足OCP原則,設計師們提出了工廠方法模式,工廠方法模式相對於簡單工廠模式來講最大的不一樣在於,對於一個項目或者一個獨立的模塊來講,簡單工廠模式只有一個工廠類,兒工廠方法模式有一組實現了相同接口的工廠類。
在工廠方法模式中,核心的工廠類再也不負責產品的建立,而是將具體的建立工做交給子類去作。這個核心工廠則變爲抽象工廠角色,僅負責給出具體工廠子類必須實現的接口,而不接觸產品建立的細節。在工廠方法模式中通常都有一個平行的等級結構,也就是說工廠和產品是對應的。
果農起初只有一個小型的蘋果園,後來規模擴大,出現了蘋果工廠,葡萄工廠,每一個工廠獨立生產對應的水果,實現專業化和規模化的生產。
/** * 工廠方法模式示例 * Created by xian.juanjuan on 2017-7-14 09:30. */ public class ClientTest { public static void main(String[] args){ //實例化水果工廠 FruitFactory fruitFactory = new AppleFactoryImpl(); FruitFactory fruitFactory1 = new GrapeFactoryImpl(); //從水果工廠生產水果 Fruit fruit = fruitFactory.factory(); Fruit fruit1 = fruitFactory1.factory(); //不一樣水果的生長過程 fruit.plant(); fruit1.harvest(); } } /** * 水果接口 */ interface Fruit{ void plant();//種植 void harvest();//收穫 } /** * 水果工廠的產品:蘋果 */ class Apple implements Fruit{ private int treeAget;//樹齡 @Override public void harvest() { System.out.println("蘋果已經收穫。。。"); } @Override public void plant() { System.out.println("蘋果已經種植。。。"); } public int getTreeAget() { return treeAget; } public void setTreeAget(int treeAget) { this.treeAget = treeAget; } } /** * 水果工廠的產品:葡萄 */ class Grape implements Fruit{ private boolean seedless;//是否有籽 @Override public void harvest() { System.out.println("葡萄已經收穫。。。"); } @Override public void plant() { System.out.println("葡萄已經種植。。。"); } public boolean isSeedless() { return seedless; } public void setSeedless(boolean seedless) { this.seedless = seedless; } } /** * 水果工廠接口 */ interface FruitFactory{ Fruit factory(); } /** * 蘋果工廠實現 */ class AppleFactoryImpl implements FruitFactory{ @Override public Fruit factory() { Fruit fruit = new Apple(); System.out.println("水工工廠成功建立一個水果:蘋果"); return fruit; } } /** * 葡萄工廠實現 */ class GrapeFactoryImpl implements FruitFactory{ @Override public Fruit factory() { Fruit fruit = new Grape(); System.out.println("水工工廠成功建立一個水果:葡萄"); return fruit; } }
輸出結果
水工工廠成功建立一個水果:蘋果
水工工廠成功建立一個水果:葡萄
蘋果正在生長。。。
葡萄已經收穫。。。
Process finished with exit code 0
抽象工廠模式是三個最抽象,最具通常性的。抽象工廠模式的目的是給客戶端提供一個接口,能夠建立多個產品族中的產品對象,使用抽象工廠模式須要知足如下條件
舉例說明兩個概念
抽象工廠模式的每一個工廠創造出的都是一族的產品,而不是一個或者一組。
用戶買手機配充電器
public class AbstractFactoryTest { public static void main(String[] args){ phoneCharging(1, 1); } public static void phoneCharging(int phoneType, int chargerType){ //手機工廠和充電器工廠生產手機和充電器 Phone phone = PhoneFactory.createPhone(phoneType); Charger charger = ChargerFactory.createCharger(chargerType); //買手機配充電器 phone.buyPhone(); charger.configureCharger(); } } /** * 手機接口 */ interface Phone{ void buyPhone();//買手機 } class AndroidPhone implements Phone{ @Override public void buyPhone() { System.out.println("我買了一部Android手機"); } } class ApplePhone implements Phone{ @Override public void buyPhone() { System.out.println("我買了一部Apple手機"); } } /** * 充電器接口 */ interface Charger{ void configureCharger();//配置充電器 } class AndroidCharger implements Charger{ @Override public void configureCharger() { System.out.println("給我配置了Android手機充電器"); } } class AppleCharger implements Charger{ @Override public void configureCharger() { System.out.println("給我配置了Apple手機充電器"); } } /** * 手機工廠類 */ class PhoneFactory{ public static Phone createPhone(int type){ Phone phone = null; if (1 == type){ phone = new AndroidPhone(); } else if (2 == type){ phone = new ApplePhone(); } return phone; } } /** * 充電器工廠類 */ class ChargerFactory{ public static Charger createCharger(int type){ Charger charger = null; if (1 == type){ charger = new AndroidCharger(); } else if(2 == type){ charger = new AppleCharger(); } return charger; } }運行結果
我買了一部Android手機
給我配置了Android手機充電器
Process finished with exit code 0
外部使用的時候,手機與充電器的類型須要匹配,若是phoneCharging(1, 2);那手機和充電器就不兼容;在上述的簡單工廠模式中,並無維護這種關係,爲了解決這個問題 須要使用抽象工廠模式。簡單工廠模式針對的是一個產品等級結構,而抽象工廠模式則須要面對多個產品等級結構。
用同一個工廠等級結構複雜兩個不一樣產品等級結構中的產品對象的建立,即Apple工廠生產Apple手機和Apple手機充電器。因爲這兩個產品族的產品等級結構相同,所以使用同一個工廠族也能夠處理這兩個產品族的建立問題,這就是抽象工廠模式。
在以前代碼的基礎上,只須要增長抽象工廠類和實現便可。
interface AbstractFactory{ Phone createPhone(); Charger createCharger(); } class AndroidFactory implements AbstractFactory{ @Override public Charger createCharger() { return new AndroidCharger(); } @Override public Phone createPhone() { return new ApplePhone(); } } class AppleFactory implements AbstractFactory{ @Override public Charger createCharger() { return new AppleCharger(); } @Override public Phone createPhone() { return new ApplePhone(); } } 測試客戶端 public class AbstractFactoryTest { public static void main(String[] args){ //客戶選擇並建立須要的產品對象 AbstractFactory factory = new AppleFactory(); //讓店員配套起來便可 phoneCharging(factory); } public static void phoneCharging(AbstractFactory factory){ //店員找相應的工廠獲取產品 Phone phone = factory.createPhone(); Charger charger = factory.createCharger(); phone.buyPhone(); charger.configureCharger(); } }因而可知,抽象工廠模式是爲一系列相關的對象或者相互依賴的對象建立一個接口。