工厂方法模式(Factory Method)简介
工廠方法模式 名字 跟已經介紹的 簡單工廠模式很類似.
實際上它們的模型也是十分相似的.
我們先看看工廠模式的定義.
一. 工廠方法(Factory Method)模式定義
教材上是這樣寫的:
工廠方法模式(Factory Method):
定義1個用于創建對象的接口, 讓子類決定實例化哪個類.?? 工廠模式使1個類的實例化延遲到其子類.
是不是覺得定義很惡心, 我也覺得, 剛開始完全看不懂啊.
這里稍稍先分析一下.
定義1個用于創建對象的接口, 讓子類決定實例化哪個類.?? 工廠模式使1個類的實例化延遲到其子類.
上面那句話出現了4個對象.
分別是: 對象 接口 類 子類
它們的關系是這樣的:
類 是指業務類,
對象 是 類? 的實例化對象.
接口 指Java 的 interface 或者 抽象類. (工廠)
(工廠)子類 會創建1個 (業務)類 的 對象
至于延遲是什么意思?? 還是在下面舉個例子來講把.
二. 手機的例子.
顯示上手機有很多種. (包括Nokia手機, BlackBerry手機)
常用的功能有3種.
1. 打電話,
2. 發郵件.
3. 播放mp3.
現在有個人很有錢任性.
他有3臺Nokia , 1臺在打電話, 一臺發郵件, 一臺聽歌..
用代碼如何實現呢.
三. 簡單工廠模式實現.
UML:
CellPhone接口:
public interface CellPhone {public abstract void call();public abstract void playMusic();public abstract void sendEmail(); }BlackBerry:
public class BlackBerry implements CellPhone {@Overridepublic void call(){System.out.println("calling by BlackBerry");}@Overridepublic void playMusic(){System.out.println("playing Music by BlackBerry");}@Overridepublic void sendEmail(){System.out.println("sending Email by BlackBerry");}}Nokia:
public class Nokia implements CellPhone {@Overridepublic void call(){System.out.println("calling by nokia");}@Overridepublic void playMusic(){System.out.println("playing Music by nokia");}@Overridepublic void sendEmail(){System.out.println("sending Email by nokia");}}
工廠類CellPhoneFactory:
public class CellPhoneFactory {public static CellPhone createCellPhone(String name){CellPhone p = null;switch(name){case "Nokia" : p = new Nokia(); break;case "BlackBerry" : p = new BlackBerry(); break;}return p;} }
客戶端:
String name = "Nokia";CellPhone p = CellPhoneFactory.createCellPhone(name);CellPhone p2 = CellPhoneFactory.createCellPhone(name);CellPhone p3 = CellPhoneFactory.createCellPhone(name);p.call();p2.sendEmail();p3.playMusic();
四. 簡單工廠的1個缺點.
簡單工廠對客戶端封裝了真正的業務類, 這是以前說過的.
但是如果我要增加1個業務, 例如那個人想用一臺Sony手機.
除了修改客戶端代碼外
那么我必須新增1個Sony類? -> 符合封閉-開放原則
五. 工廠方法的實現.
UML:
其中CellPhone, BlackBerry, Nokia3個類或接口跟上面是一樣的沒有變化.
工廠抽象類CellPhoneFactory:
現在這個類變成了抽象類了. public abstract class CellPhoneFactory {public abstract CellPhone createCellPhone(); }
NokiaFactory:
Nokia工廠, 只會創建Nokia對象,? 而且創建對象的方法已經不是靜態方法, 需要實例化1個工廠來創建.
public class NokiaFactory extends CellPhoneFactory{@Overridepublic CellPhone createCellPhone(){return new Nokia();} }BlackBerryFactory:
public class BlackBerryFactory extends CellPhoneFactory{@Overridepublic CellPhone createCellPhone(){return new BlackBerry();} }客戶端代碼:
CellPhoneFactory factory = new NokiaFactory();CellPhone p = factory.createCellPhone();CellPhone p2 = factory.createCellPhone();CellPhone p3 = factory.createCellPhone();p.call();p2.sendEmail();p3.playMusic();
六. 工廠方法與簡單工廠方法的區別.
好了, 通過對比, 我們知道區別如下:
1. 簡單工廠的工廠類是1個非抽象類.? 而工廠方法的工廠類是一個抽象類(或者接口), 它下面還有子類.
2. 簡單工廠的業務類對象由工廠類的靜態方法直接創建, 而工廠方法的業務類對象由工廠類的子類來創建.
這個就是工廠方法里, 那句" 工廠模式使1個類的實例化延遲到其子類" 的原因,? 延遲是相當于簡單工廠來講的.
如果要新增1個sony手機.
工廠方法, 除了修改客戶端代碼之外,
還需要
新加個sony手機類.
新家1個sony手機工廠類.
看起來是完全符合開放-封閉原則的.
但是實際上,? 簡單工廠方法的判斷在工廠類的switch字句內.
而工廠方法看起來不需要判斷, 但實際上是把判斷交給了客戶端.
也就是說這一句
客戶端需要自己判斷使用哪個工廠.
而簡單工廠只需要傳入"Nokia"的名字就得到對應的業務對象.
有沒有折中方法呢? 就是只需要手機名字的參數,? 而且符合開放封閉原則的寫法.
那就需要利用java里的反射機制.(所謂反射就是可以根據類名獲取哪個類的對象或其他資源)
七. 反射簡單工廠.
重寫簡單工廠的工廠類,?? 不使用switch 字句, 而是java的反射..
public class CellPhoneReflectFactory {public static CellPhone createCellPhone(String name){Class<?> c = null;Class<?>[] argTypes = {}; //指明所要調用的構造方法的形參 Constructor<?> cst = null;CellPhone p = null;Object obj = null;try {c = (Class<?>) Class.forName("factory.simple." + name);cst = c.getConstructor(argTypes);//獲取指定參數的構造方法obj = cst.newInstance(argTypes);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}p = (CellPhone)obj;return p;} }而客戶端的寫發不需要改變, 新增業務類也無需修改這個工廠類了.
總結
以上是生活随笔為你收集整理的工厂方法模式(Factory Method)简介的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 代理模式(Proxy)简介
- 下一篇: 模板方法模式(TemplateMetho