寫在前面的話:
雖然在我們的日常開發過程中,不用設計模式也可以完成相應的功能,但是用好的設計模式可以幫助我們更好的解決實際問題,設計模式一個重要的思想是解耦,降低代碼間的粘着性。幾乎我們所有的java框架和源碼都使用了良好的設計模式,比如spring就使用了諸如BeanFactory的工廠模式,mybatis框架的模板模式等等。學習設計模式可以更好的讓我們把業務轉化成技術實現。
工廠模式從名字上來看,脫離於現實生活中的工廠,就是生成和製造各種產品的,比如口罩工廠。在Java的世界裏,工廠模式,也是同樣的道理,也是用來生產東西的(類實例對象)。在沒有該模式的情況下,我們一般生產對象(創建對象)一般都是採用new的形式。那爲什麼有了new的方式,還要提出一種“工廠模式”呢?原因其實還是比較容易理解,就比如這個生產口罩的工廠內部,口罩分多鐘型號,KN94/KN95/KF94等等。假如一個公民想要買口罩,我得告訴工廠我要哪種型號的吧,然後它生產出來給我。但生產某種型號的過程我是不知道的,不知道用了什麼材料,不知道用了什麼工藝對吧? 然後反過來想new的這種方式,一般代碼爲KouZhao kouZhao = new
KouZhao()
,使用new 的前提是什麼?得先知道KouZhao這個類吧,也就是說我得知道KouZhao是要用什麼材料用什麼工藝來做的,工廠模式就是 將這個過程隱藏起來只給結果給調用方。
1.簡單工廠模式
簡單工廠就是我給你型號,你幫我生產,隱藏生產過程。new是我自己知道這個型號的製作過程和原理,自己申明生產過程。就 是傳入一個型號名稱(形參),內部if-else去判斷生產對象型號名稱的口罩。如果要新增型號,只能修改該工廠內部的if-else語句,新增判斷。
KouZhaoFactory factory = new KouZhaoFactory();
KN94KouZhao kn94 = (KN94KouZhao) factory.create("KN94");
KN95KouZhao kn95 = (KN95KouZhao) factory.create("KN95");
KF94KouZhao kf94 = (KF94KouZhao) factory.create("KF94");
kn94.protect();
kn95.protect();
kf94.protect();
爲了避免字符串寫錯造成的問題可以使用反射改進一下:
KouZhaoFactory代碼如下:
KouZhao create(Class <? extends KouZhao> clazz){
try {
if (clazz!=null) {
return clazz.newInstance();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
測試方法如下:
KouZhaoFactory factory = new KouZhaoFactory();
KN94KouZhao kn94 =(KN94KouZhao) factory.create(KN94KouZhao.class);
KN95KouZhao kn95 =(KN95KouZhao) factory.create(KN95KouZhao.class);
KF94KouZhao kf94 =(KF94KouZhao) factory.create(KF94KouZhao.class);
kn94.protect();
kn95.protect();
kf94.protect();
從上面可以看出簡單工廠模式中工廠類的職責相對過重,所有的判斷和創建都在內部完成,不易於擴展過於複雜的產品結構。
2.工廠方法模式
簡單工廠模式看起來像一個萬能工廠啥型號的口罩都可生成,工廠類的職責過重了,工廠方法模式是對簡單工廠進行了升級,不在由工廠類生成具體的口罩了,而是產生一個抽象的口罩接口,我們先創建一個口罩接口,再創建KN94、KN95、KF94實現類實現口罩接口。在使用時,直接給工廠傳入指定的實現類,內部利用反射的機制,綁定創建好指定型號(類型)的口罩。類圖如下:
測試代碼:
KouZhaoFactory factory = new KN94KouZhaoFactory();
KouZhao kn94 = factory.create();
kn94.protect();
KouZhaoFactory factory2 = new KN95KouZhaoFactory();
KouZhao kn95 = factory2.create();
kn95.protect();
KouZhaoFactory factory3 = new KF94KouZhaoFactory();
KouZhao kf94 = factory3.create();
kf94.protect();
從上面可以看出工廠方法模式中類的過多比簡單工廠模式幾乎多了1倍,系統的複雜度也隨之增加,理解起來不是那麼容易。
3.抽象工廠模式
現實中一個工廠很少只生成1中產品的,通常情況都是如下圖所示:
我們將1個工廠相同顏色的各種產品稱作1個產品族,不同工廠的相同產品稱作1個產品等級結構,即上圖中的x軸和y軸。
在我們java世界裏抽象工廠模式源於此, 抽象工廠模式是工廠方法的升級。假設現在用戶想要購買口罩了,突然又想買點繃帶備用,如果沒有這個產品就很尷尬了,使用抽象工廠可以給用戶更多的選擇。類圖如下:
測試代碼:
KouZhaoFactory factory = new KN94KouZhaoFactory();
factory.createBengDai().blood();
factory.createHuMuJing().protectEyes();
factory.createKouZhao().protect();
KouZhaoFactory factory2 = new KN95KouZhaoFactory();
factory2.createBengDai().blood();
factory2.createHuMuJing().protectEyes();
factory2.createKouZhao().protect();
KouZhaoFactory factory3 = new KF94KouZhaoFactory();
factory3.createBengDai().blood();
factory3.createHuMuJing().protectEyes();
factory3.createKouZhao().protect();
總結:抽象工廠模式可以完美的展現出產品族和產品等級的關係,適用於產品數量不多的情況,過多的產品會使系統複雜度成倍遞增。