設計模式の工廠模式
簡單工廠模式
-
簡單工廠模式是屬於建立型模式,是工廠模式的一種。簡單工廠模式是由一個工廠物件決定創建出哪一種產品類的例項。
-
簡單工廠模式是工廠模式家族中最簡單實用的模式
-
簡單工廠模式:定義了一個建立物件的類,由這個類來封裝例項化物件的行為(程式碼)
-
在軟體開發中,當我們會用到大量的建立某種、某類或者某批物件時,就會使用到工廠模式.
-
手機制造頂層介面
public interface Phone { void make(); }
-
小米制造商
public class XiaoMiPhone implements Phone { @Overridepublic void make() { System.out.println("製造了一臺小米手機"); } }
-
華為製造商
public class HuaWeiPhone implements Phone{ @Override public void make() { System.out.println("製造了一臺華為手機"); } }
-
手機制造代工廠(富士康)
public class PhoneFactory { public Phone makePhone(String phoneType){if ("xiaomi".equals(phoneType)){ return new XiaoMiPhone(); }else if ("huawei".equals(phoneType)){ return new HuaWeiPhone(); } return null; } }
-
使用者需求方
public class TestMain { public static void main(String[] args) { PhoneFactory phoneFactory= new PhoneFactory(); Phone xiaomi = phoneFactory.makePhone("xiaomi"); xiaomi.make(); Phone huawei = phoneFactory.makePhone("huawei"); huawei.make(); } }
-
類圖如下所示
通過上面製造手機的列子可以看出,此時我們的工廠只能生產華為和小米兩款手機
如果想要生辰更多的品牌手機,那就的在工廠中加條件適配
沒增加一個手機品牌,就要去修改工廠的原始碼,這種操作不符合開閉原則
但是我們可以對其進行優化,使其符合開閉原則
// public Phone makePhone(String phoneType){ // if ("xiaomi".equals(phoneType)){ // return new XiaoMiPhone(); // }else if ("huawei".equals(phoneType)){ // return new HuaWeiPhone(); // } // return null; // } public Phone makePhoneOptimize(Class <? extends Phone> clazz){ if (null != clazz){ try { return clazz.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } return null; }
然後使用者對應的使用方式也跟著改變一下
// PhoneFactory phoneFactory = new PhoneFactory(); // Phone xiaomi = phoneFactory.makePhone("xiaomi"); // xiaomi.make(); // Phone huawei = phoneFactory.makePhone("huawei"); // huawei.make(); PhoneFactory phoneFactory = new PhoneFactory(); Phone xiaomi = phoneFactory.makePhoneOptimize(XiaoMiPhone.class); xiaomi.make(); Phone huawei = phoneFactory.makePhoneOptimize(HuaWeiPhone.class); huawei.make(); }
這樣,即使我們繼續擴充套件更多的品牌生產線,也可以不用動這一部分的原始碼了
簡單工廠模式在很多地方都在使用,
比如日曆類Calendar.getInstance()方法
或者logback中到 LoggerFactory 中有多個過載的方法 getLogger()
簡單工廠的缺點就是,工廠類的職責相對過重,不易於擴充套件過於複雜的產品結構
工廠方法模式
-
和簡單工廠模式相比,工廠方法模式將生成具體產品的任務分發給具體的產品工廠,而不是由一個大工廠聚合生產
-
Phone 、XiaoMiPhone、HuaWeiPhone 類的不變
-
新增抽象工廠類、小米工廠類、華為工廠類即可
-
總工廠介面
public interface PhoneFactory { Phone makePhone(); }
-
小米工廠類
public class XiaoMiFactory implements PhoneFactory {
@Override
public Phone makePhone() {
// 這裡的方式是:;若生產何種產品完全由工廠決定,則這裡不應該傳入控制生產的引數。
// 如果消費者知道自己想要什麼產品,可以入參,用引數來區別對待生產不同的產品。像簡單工廠模式一一致
return new XiaoMiPhone();
}
}
-
華為工廠類
public class HuaWeiFactory implements PhoneFactory {
@Override
public Phone makePhone() {
// 這裡的方式是:;若生產何種產品完全由工廠決定,則這裡不應該傳入控制生產的引數。
// 如果消費者知道自己想要什麼產品,可以入參,用引數來區別對待生產不同的產品。像簡單工廠模式一一致
return new HuaWeiPhone();
}
}
-
使用者需求方
public class TestMain { public static void main(String[] args) { PhoneFactory xiaoMiFactory = new XiaoMiFactory(); PhoneFactory huaWeiFactory = new HuaWeiFactory(); Phone xiaomi = xiaoMiFactory.makePhone(); Phone huawei = huaWeiFactory.makePhone(); xiaomi.make(); huawei.make(); } }
-
類圖如下所示
在簡單工程模式中,最後我們使用反射的方式實現開閉原則
但是如果沒餓過課程的建立邏輯有區別的話,工廠的職責就會越加繁重,不利於維護
根據單一職責原則,我們可以將職能進行劃分
最大的工廠只負責約束管理
其下允許動態建立其他幹實事的小工廠
就比如富士康只負責談需求,接單,產品驗收
但其下的子工廠或者找個外包工廠(自由擴充套件)來幹活
工廠方法模式和簡單工廠的區別就在於
簡單工廠只有一個工廠,負責產品的建立和銷售
工廠方法模式,有一個最大的工廠負責制定規章制度,旗下有很多專一的小工廠來負責生產和銷售
抽象工廠模式
-
定義了一個 interface 用於建立相關或有依賴關係的物件簇,而無需指明具體的類
-
抽象工廠模式可以將簡單工廠模式和工廠方法模式進行整合。
-
從設計層面看,抽象工廠模式就是對簡單工廠模式的改進(或者稱為進一步的抽象)
-
將工廠抽象成兩層,AbsFactory(抽象工廠) 和 具體實現的工廠子類。程式設計師可以根據建立物件型別使用對應的工廠子類。這樣將單個的簡單工廠類變成了工廠簇,更利於程式碼的維護和擴充套件。
-
上面的工廠模式都是在圍繞手機在生產,如果這個時候,我們新增一個PC領域進去該如何玩呢?
-
手機制造頂級介面
public interface Phone { void make(); }
-
小米手機制造商
public class XiaoMiPhone implements Phone { @Override public void make() { System.out.println("製造了一臺小米手機"); } }
-
華為手機制造商
public class HuaWeiPhone implements Phone { @Override public void make() { System.out.println("製造了一臺華為手機"); } }
-
筆記本製造頂級介面
public interface PC { void make(); }
-
小米筆記本製造商
public class XiaoMiPC implements PC{ @Override public void make() { System.out.println("生產了一臺小米筆記本"); } }
-
華為筆記本製造商
public class HuaWeiPC implements PC{ @Override public void make() { System.out.println("生產了一臺華為筆記本"); } }
-
代工廠頂級介面
public interface AbstractFactory { Phone makePhone(); PC makePC(); }
-
小米代工廠製造介面
public class XiaoMiFactory implements AbstractFactory { @Override public Phone makePhone() { // 這裡的方式是:;若生產何種產品完全由工廠決定,則這裡不應該傳入控制生產的引數。 // 如果消費者知道自己想要什麼產品,可以入參,用引數來區別對待生產不同的產品。想簡答工廠模式一一致 return new XiaoMiPhone(); } @Override public PC makePC() { // 這裡的方式是:;若生產何種產品完全由工廠決定,則這裡不應該傳入控制生產的引數。 // 如果消費者知道自己想要什麼產品,可以入參,用引數來區別對待生產不同的產品。想簡答工廠模式一一致 return new XiaoMiPC(); } }
-
華為代工廠製造介面
public class HuaWeiFactory implements AbstractFactory { @Override public Phone makePhone() { // 這裡的方式是:;若生產何種產品完全由工廠決定,則這裡不應該傳入控制生產的引數。 // 如果消費者知道自己想要什麼產品,可以入參,用引數來區別對待生產不同的產品。想簡答工廠模式一一致 return new HuaWeiPhone(); } @Override public PC makePC() { // 這裡的方式是:;若生產何種產品完全由工廠決定,則這裡不應該傳入控制生產的引數。 // 如果消費者知道自己想要什麼產品,可以入參,用引數來區別對待生產不同的產品。想簡答工廠模式一一致 return new HuaWeiPC(); } }
-
需求方
public class TestMain { public static void main(String[] args) { AbstractFactory xiaoMiFactory = new XiaoMiFactory(); AbstractFactory huaWeiFactory = new HuaWeiFactory(); Phone xiaomi = xiaoMiFactory.makePhone(); PC xiaomiPC = xiaoMiFactory.makePC(); Phone huawei = huaWeiFactory.makePhone(); PC huaweiPC = huaWeiFactory.makePC(); xiaomi.make(); xiaomiPC.make(); huawei.make(); huaweiPC.make(); } }
-
類圖如下所示
-
此時,如果我們覺得手機和筆記本都已經玩膩了,想進軍造車行業
-
定義造成頂級介面
-
定義造車品牌實現介面,比如小鵬汽車,蔚來汽車等
-
此時增加代工頂級介面一個允許生產汽車的行為,並寫一個汽車代工廠即可工廠
-
擴充套件性就大大的增加了
小米公司可以生產手機和膝上型電腦
華為公司可以生成手機和膝上型電腦
如果此時我們還想繼續追加他的功能職責,比如生產無人機
這個時候就要定義一個無人機的頂級介面
然後小米和華為都要再定義一個無人機的實現類
然後再在代工廠頂級介面中新增一個生產無人機的方法(開閉原則被破壞)
最後小米和華為的Factory,重寫代工廠頂級介面中方法,實現無人機的生產(開閉原則被破壞)
使用的時候,如上方使用程式碼差異無二
因此抽象工程模式也是有很大缺點的,維護難度加大,理解難度加大
擴充套件時 - > 代工廠頂級介面需要維護
擴充套件時 - > 代工廠頂級介面的實現工廠也要維護實現對應方法
但是在實際應用中,我們新增一個功能職責的週期是很長的,只要不是頻繁新增,這種設計模式仍然適合我們
抽象工廠模式在Spring中的應用是最為廣泛的一種設計模式
工廠模式小結
-
工廠模式的意義
-
將例項化物件的程式碼提取出來,放到一個類中統一管理維護,達到和主專案的依賴關係的解耦。從而提高專案的擴充套件和維護性。
-
-
三種工廠模式 (簡單工廠模式、工廠方法模式、抽象工廠模式)
-
設計模式的依賴抽象原則
-
建立物件例項時,不要直接 new 類, 而是把這個 new 類的動作放在一個工廠的方法中,並返回
-
不要讓類繼承具體類,而是繼承抽象類或者是實現 interface(介面)
-
Ø 不要覆蓋基類中已經實現的方法。
-