如果下面的代碼你能輕易閱讀,那么你已經熟悉工廠模式,可以接着學習其他的設計模式。
factory.jpg
工廠模式:一個類或對象中往往會包含別的對象,在創建這種成員對象時。我們經常使用new來創建,但是這會導致相關的兩個類之間產生依賴性。工廠模式使用了一個方法來決定使用究竟實例哪個類。
簡單工廠
工廠模式,即類似於工廠一樣有一個流程化的形式。
比方說服裝廠,先是任意一種服裝的制作,然后是漂洗,最后是包裝出場。
寫成代碼如下所示。
/* simple-factory.ts */ import CloseTypeEnum from './close-type-enum'; class SimpleFactory { private static _instance: SimpleFactory; public static get instance() { if (!this._instance) { this._instance = new SimpleFactory(); } return this._instance; } public createClose(closeType: CloseTypeEnum): string { let closeName: string = null; switch (closeType) { case CloseTypeEnum.Sweater: closeName = 'sweater'; break; case CloseTypeEnum.Shirt: closeName = 'shirt'; break; case CloseTypeEnum.Jacket: closeName = 'jacket'; break; default : throw new Error('can\'t find type' + closeType); } this.washingsClose(closeName); this.packagingClose(closeName); return closeName; } public washingsClose(close: string) {} public packagingClose(close: string) {} }
用一個類來創建經過一系列流程對象,對象的創建和流程解除依賴。從而解除依賴,更容易增加對象種類。便於以后維護和擴展。
抽象工廠
如上面的服裝廠的流程,我們的服裝廠要增加一種衣服的類型時,仍然需要進入工廠類中增加一個case。如果每一個case里面的流程是非常復雜的,那我們用switch case顯然是不合適的。
這時候我們需要用到抽象工廠。
將生產衣服的這個switch case抽象成一個接口,因為我們只關心最終造出來的衣服,而不關心制作的流程。
換成代碼就是寫幾個方法都去實現makeClose的接口。
/* i-factory-interface.ts */ interface ICloseMakerFactory { makeClose(): IClose } interface IClose { name: string price: number note: string } export { ICloseMakerFactory, IClose, }; /* sweater-producer.ts */ import { IClose, ICloseMakerFactory } from '../i-factory-interface'; export default class SweaterProducer implements ICloseMakerFactory { makeClose(): IClose { return { name: 'sweater', price: 15, note: 'The process can be complex', }; } } /* shirt-producer.ts */ import { IClose, ICloseMakerFactory } from '../i-factory-interface'; export default class ShirtProducer implements ICloseMakerFactory { makeClose(): IClose { return { name: 'shirt', price: 20, note: 'The process can be complex', }; } } **/* jacket-producer.ts */ import { IClose, ICloseMakerFactory } from '../i-factory-interface'; export default class JacketProducer implements ICloseMakerFactory { makeClose(): IClose { return { name: 'jacket', price: 25, note: 'The process can be complex', }; } }**
然后在主方法中調用這些方法去實現生產衣服的過程。
class AbstractFactory { private static _instance: AbstractFactory; private closeTypeAnalyzerMapping: Map<CloseTypeEnum, ICloseMakerFactory>; constructor() { this.closeTypeAnalyzerMapping.set(CloseTypeEnum.Jacket, new JacketProducer()); this.closeTypeAnalyzerMapping.set(CloseTypeEnum.Shirt, new ShirtProducer()); this.closeTypeAnalyzerMapping.set(CloseTypeEnum.Sweater, new SweaterProducer()); } public static get instance() { if (!this._instance) { this._instance = new AbstractFactory(); } return this._instance; } public makeCloseTypeAnalyzer(type: CloseTypeEnum): ICloseMakerFactory { if (this.closeTypeAnalyzerMapping.has(type)) { return this.closeTypeAnalyzerMapping.get(type); } else { throw new Error('our factory don\'t have this type'); } } } const shrit= AbstractFactory.instance.makeCloseTypeAnalyzer(CloseTypeEnum.Shirt).makeClose();
當然,實際場景中過程的每一步都會根據衣服的種類有多種實現方法,我們可以按照生產衣服一樣將他們區分開來。
這樣,未來我們增加了一種衣服的類型或者洗滌方法等,只需要增加一個實現類而不用大面積的改變主方法。
工廠模式的利弊
利:
- 消除對象間的耦合:
使用工廠方法而不是new關鍵字,解除創建過程中的耦合步驟,增加可維護性和可測試性。 - 易於模塊化
使用工廠模式,可以先創建一個抽象的父類,然后在子類中創建工廠方法,從而把成員對象的實例化推遲到更專門的子類中進行。增加可拓展性。
弊:
工廠模式在處理多流程或者是根據上下文創建實例的情況下非常好用。但是在單一流程或者是不需要根據上下文創建對象的情況下使用反而會增加閱讀成本。
所以我們應該在恰當的場景中使用工廠模式。如果拿不定主意,那就不要使用,因為在以后的重構中還有機會使用工廠模式。
作者:我不叫奇奇
鏈接:https://www.jianshu.com/p/fe7f77f55a5b
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
