Java-工廠設計模式
- 2019 年 10 月 14 日
- 筆記
一、關於工廠設計模式
介紹:設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。在工廠模式中,我們在創建對象時不會對客戶端暴露創建邏輯,
並且是通過使用一個共同的介面來指向新創建的對象。
意圖:定義一個創建對象的介面,讓其子類自己決定實例化哪一個工廠類,工廠模式使其創建過程延遲到子類進行。
主要解決:主要解決介面選擇的問題。
何時使用:我們明確地計劃不同條件下創建不同實例時。
如何解決:讓其子類實現工廠介面,返回的也是一個抽象的產品。
分類:普通簡單工廠、多個方法的簡單工廠、多個靜態方法的簡單工廠、工廠設計模式。
二、程式碼實現
簡單工廠:就是建立一個工廠類,對實現了同一介面的一些類進行實例的創建。首先看下關係圖
舉例如下:(我們舉一個發送郵件和簡訊的例子)
首先,創建二者的共同介面:
Sender
package pers.hupo.hupow.factory; /** * @author hupo * 創建一個介面 * */ public interface Sender { void Send(); }
其次,創建實現類:
MailSender
package pers.hupo.hupow.factory; /** * @author hupo * Sender實現類 * */ public class MailSender implements Sender { @Override public void Send() { System.out.println("this mail message"); } }
SmsSender
package pers.hupo.hupow.factory; /** * @author hupo * Sender實現類 * */ public class SmsSender implements Sender { @Override public void Send() { System.out.println("this sms message"); } }
最後,建工廠類
package pers.hupo.hupow.factory; /** * @author hupo * 工廠類 * */ public class SendFactory { public Sender produce(String type) { if ("mail".equals(type)) { return new MailSender(); } if ("sms".equals(type)) { return new SmsSender(); } return null; } }
測試方法
package pers.hupo.hupow.factory; public class FactoryTest { public static void main(String[] args) {
SendFactory sendFactory = new SendFactory(); Sender sender = sendFactory.produce("sms"); sender.Send(); } }
輸出結果:
this sms message
多個方法的簡單工廠:是對普通工廠方法模式的改進,在普通工廠方法模式中,如果傳遞的字元串出錯,則不能正確創建對象,
而多個工廠方法模式是提供多個工廠方法,分別創建對象。關係圖如下
將工廠類改動一些 如下:
package pers.hupo.hupow.factory; /** * @author hupo * 工廠類 * */ public class SendFactory { /* * 多方法的簡單工廠 */ public Sender produceMail() { return new MailSender(); } public Sender produceSms() { return new SmsSender(); } }
修改一下測試類
SendFactory sendFactory = new SendFactory(); Sender sender = sendFactory.produceMail(); sender.Send();
輸出結果:
this mail message
多個靜態方法簡單工廠:將上面的多個工廠類里的方法置為靜態的,不需要創建實例,直接調用即可。如下
package pers.hupo.hupow.factory; /** * @author hupo * 工廠類 * */ public class SendFactory { /* * 靜態多方法工廠 * */ public static Sender produceMail() { return new MailSender(); } public static Sender produceSms() { return new SmsSender(); } }
測試
/*靜態多方法*/ Sender sender = SendFactory.produceMail(); sender.Send();
輸出:
this mail messageb
總體來說,簡單工廠模式適合:凡是出現了大量的產品需要創建,並且具有共同的介面時,可以通過工廠方法模式進行創建。在以上的三種模式中,
第一種如果傳入的字元串有誤,不能正確創建對象(當然你可以做一個返回報錯資訊的類),第三種相對於第二種,不需要實例化工廠類,所以,大多數情況下,我們會選用第三種——靜態工廠方法模式。
三、工廠方法模式(Factory Method)
簡單工廠模式有一個問題就是,類的創建依賴工廠類,也就是說,如果想要拓展程式,必須對工廠類進行修改,這違背了閉包原則。
所以,從設計角度考慮,有一定的問題,如何解決?就用到工廠方法模式,創建一個工廠介面和創建多個工廠實現類,這樣一旦需要增加新的功能,直接增加新的工廠類就可以了,不需要修改之前的程式碼。
首先還是創建發送資訊端的介面
Sender
package pers.hupo.hupow.FactoryMethod; /** * @author hupo * 工廠方法設計模式-資訊介面 */ public interface Sender { void Send(); }
兩個實現類
MailSender
package pers.hupo.hupow.FactoryMethod; /** * @author hupo * 工廠方法設計模式-實現類 * */ public class MailSender implements Sender { @Override public void Send() { System.out.println("this is mailSender"); } }
SmsSender
package pers.hupo.hupow.FactoryMethod; /** * @author hupo * 工廠方法設計模式-實現類 * */ public class SmsSender implements Sender { @Override public void Send() { System.out.println("this is smsSender"); } }
然後再來創造工廠類介面(大內統管( ̄▽ ̄)”)
Provider
package pers.hupo.hupow.FactoryMethod; /** * @author hupo * 工廠方法設計模式-工廠類介面 * */ public interface Provider { Sender produce(); }
實現類工廠
SendMailFactory
package pers.hupo.hupow.FactoryMethod; /** * @author hupo * 工廠類設計方法-實現方法 * */ public class SendMailFactory implements Provider { @Override public Sender produce() { return new MailSender(); } }
SendSmsFactory
package pers.hupo.hupow.FactoryMethod; /** * @author hupo * 介面實現方法 * */ public class SendSmsFactory implements Provider { @Override public Sender produce() { return new SmsSender(); } }
完成之後寫個測試類來試試
package pers.hupo.hupow.FactoryMethod; /** * @author hupo * 測試類 * */ public class FactoryMethodTest { public static void main(String[] args) { Provider provider = new SendMailFactory(); Sender sender = provider.produce(); sender.Send(); } }
輸出結果
this is mailSender
加個工廠類擴展試試
添加哲學家van 和Billy 繼承sender
van
package pers.hupo.hupow.FactoryMethod; public class VanSender implements Sender { @Override public void Send() { System.out.println("f♂ck y♂u"); } }
View Code
Billy
package pers.hupo.hupow.FactoryMethod; public class BillySender implements Sender { @Override public void Send() { System.out.println("帕秋莉♂GO"); } }
View Code
然後使用SendBillyFactory 繼承Provider
package pers.hupo.hupow.FactoryMethod; public class SendBillyFactory implements Provider { @Override public Sender produce() { return new BillySender(); } }
View Code
測試類
/*哲學家測試*/ Provider provider = new SendBillyFactory(); Sender sender = provider.produce(); sender.Send();
View Code
輸出:
帕秋莉♂GO
其實這個模式的好處就是,如果你現在想增加一個功能:發及時資訊,則只需做一個實現類,實現Sender介面,同時做一個工廠類,實現Provider介面,就OK了,無需去改動現成的程式碼。這樣做,拓展性較好!