Typescript 設計模式之工廠方法
本文轉載自微信公眾號「全棧修仙之路」,作者阿寶哥 。轉載本文請聯(lián)系全棧修仙之路公眾號。
在現(xiàn)實生活中,工廠是負責生產(chǎn)產(chǎn)品的,比如牛奶、面包或禮物等,這些產(chǎn)品滿足了我們日常的生理需求。此外,在日常生活中,我們也離不開大大小小的系統(tǒng),這些系統(tǒng)是由不同的組件對象構成。
作為一名 Web 軟件開發(fā)工程師,在軟件系統(tǒng)的設計與開發(fā)過程中,我們可以利用設計模式來提高代碼的可重用性、可擴展性和可維護性。在眾多設計模式當中,有一種被稱為工廠模式的設計模式,它提供了創(chuàng)建對象的最佳方式。
工廠模式可以分為三類:
- 簡單工廠模式(Simple Factory Pattern)
- 工廠方法模式(Factory Method Pattern)
- 抽象工廠模式(Abstract Factory Pattern)
本文阿寶哥將介紹簡單工廠模式與工廠方法模式,而抽象工廠模式將在后續(xù)的文章中介紹,下面我們先來介紹簡單工廠模式。
一、簡單工廠模式
1.1 簡單工廠模式簡介
簡單工廠模式又叫 靜態(tài)方法模式,因為工廠類中定義了一個靜態(tài)方法用于創(chuàng)建對象。簡單工廠讓使用者不用知道具體的參數(shù)就可以創(chuàng)建出所需的 ”產(chǎn)品“ 類,即使用者可以直接消費產(chǎn)品而不需要知道產(chǎn)品的具體生產(chǎn)細節(jié)。
相信對于剛接觸簡單工廠模式的小伙伴來說,看到以上的描述可能會覺得有點抽象。這里為了讓小伙伴更好地理解簡單工廠模式,阿寶哥以用戶買車為例,來介紹一下 BMW 工廠如何使用簡單工廠模式來生產(chǎn)。
在上圖中,阿寶哥模擬了用戶購車的流程,pingan 和 qhw 分別向 BMW 工廠訂購了 BMW730 和 BMW840 型號的車型,接著工廠按照對應的模型進行生產(chǎn)并在生產(chǎn)完成后交付給用戶。接下來,阿寶哥將介紹如何使用簡單工廠來描述 BMW 工廠生產(chǎn)指定型號車子的過程。
1.2 簡單工廠模式實戰(zhàn)
定義 BMW 抽象類
- abstract class BMW {
- abstract run(): void;
- }
創(chuàng)建 BMW730 類(BMW 730 Model)
- class BMW730 extends BMW {
- run(): void {
- console.log("BMW730 發(fā)動咯");
- }
- }
創(chuàng)建 BMW840 類(BMW 840 Model)
- class BMW840 extends BMW {
- run(): void {
- console.log("BMW840 發(fā)動咯");
- }
- }
創(chuàng)建 BMWFactory 工廠類
- class BMWFactory {
- public static produceBMW(model: "730" | "840"): BMW {
- if (model === "730") {
- return new BMW730();
- } else {
- return new BMW840();
- }
- }
- }
生產(chǎn)并發(fā)動 BMW730 和 BMW840
- const bmw730 = BMWFactory.produceBMW("730");
- const bmw840 = BMWFactory.produceBMW("840");
- bmw730.run();
- bmw840.run();
以上代碼運行后的輸出結果為:
- BMW730 發(fā)動咯
- BMW840 發(fā)動咯
通過觀察以上的輸出結果,我們可以知道我們的 BMWFactory 已經(jīng)可以正常工作了。在 BMWFactory 類中,阿寶哥定義了一個 produceBMW() 方法,該方法會根據(jù)傳入的模型參數(shù)來創(chuàng)建不同型號的車子。
看完簡單工廠模式實戰(zhàn)的示例,你是不是覺得簡單工廠模式還是挺好理解的。那么什么場景下使用簡單工廠模式呢?要回答這個問題我們需要來了解一下簡單工廠的優(yōu)缺點。
1.3 簡單工廠模式優(yōu)缺點
1.3.1 優(yōu)點
- 將創(chuàng)建實例與使用實例的任務分開,使用者不必關心對象是如何創(chuàng)建的,實現(xiàn)了系統(tǒng)的解耦;
- 客戶端無須知道所創(chuàng)建的具體產(chǎn)品類的類名,只需要知道具體產(chǎn)品類所對應的參數(shù)即可。
1.3.2 缺點
- 由于工廠類集中了所有產(chǎn)品創(chuàng)建邏輯,一旦不能正常工作,整個系統(tǒng)都要受到影響。
- 系統(tǒng)擴展困難,一旦添加新產(chǎn)品就不得不修改工廠邏輯,在產(chǎn)品類型較多時,也有可能造成工廠邏輯過于復雜,不利于系統(tǒng)的擴展和維護。
- 了解完簡單工廠的優(yōu)缺點,我們來看一下它的應用場景。
1.4 簡單工廠模式應用場景
在滿足以下條件下可以考慮使用簡單工廠模式:
- 工廠類負責創(chuàng)建的對象比較少:由于創(chuàng)建的對象比較少,不會造成工廠方法中業(yè)務邏輯過于復雜。
- 客戶端只需知道傳入工廠類靜態(tài)方法的參數(shù),而不需要關心創(chuàng)建對象的細節(jié)。
介紹完簡單工廠模式,接下來我們來介紹本文的主角 ”工廠方法模式“。
二、工廠方法模式
2.1 工廠方法簡介
工廠方法模式(Factory Method Pattern)又稱為工廠模式,也叫多態(tài)工廠(Polymorphic Factory)模式,它屬于類創(chuàng)建型模式。
在工廠方法模式中,工廠父類負責定義創(chuàng)建產(chǎn)品對象的公共接口,而工廠子類則負責生成具體的產(chǎn)品對象, 這樣做的目的是將產(chǎn)品類的實例化操作延遲到工廠子類中完成,即通過工廠子類來確定究竟應該實例化哪一個具體產(chǎn)品類。
在上圖中,阿寶哥模擬了用戶購車的流程,pingan 和 qhw 分別向 BMW 730 和 BMW 840 工廠訂購了 BMW730 和 BMW840 型號的車型,接著工廠按照對應的模型進行生產(chǎn)并在生產(chǎn)完成后交付給用戶。接下來,阿寶哥來介紹如何使用工廠方法來描述 BMW 工廠生產(chǎn)指定型號車子的過程。
2.2 工廠方法實戰(zhàn)
定義 BMW 抽象類
- abstract class BMW {
- abstract run(): void;
- }
創(chuàng)建 BMW730 類(BMW 730 Model)
- class BMW730 extends BMW {
- run(): void {
- console.log("BMW730 發(fā)動咯");
- }
- }
創(chuàng)建 BMW840 類(BMW 840 Model)
- class BMW840 extends BMW {
- run(): void {
- console.log("BMW840 發(fā)動咯");
- }
- }
定義 BMWFactory 接口
- interface BMWFactory {
- produceBMW(): BMW;
- }
創(chuàng)建 BMW730Factory 類
- class BMW730Factory implements BMWFactory {
- produceBMW(): BMW {
- return new BMW730();
- }
- }
創(chuàng)建 BMW840Factory 類
- class BMW840Factory implements BMWFactory {
- produceBMW(): BMW {
- return new BMW840();
- }
- }
生產(chǎn)并發(fā)動 BMW730 和 BMW840
- const bmw730Factory = new BMW730Factory();
- const bmw840Factory = new BMW840Factory();
- const bmw730 = bmw730Factory.produceBMW();
- const bmw840 = bmw840Factory.produceBMW();
- bmw730.run();
- bmw840.run();
通過觀察以上的輸出結果,我們可以知道我們的 BMW730Factory 和 BMW840Factory 工廠已經(jīng)可以正常工作了。相比前面的簡單工廠模式,工廠方法模式通過創(chuàng)建不同的工廠來生產(chǎn)不同的產(chǎn)品。下面我們來看一下工廠方法有哪些優(yōu)缺點。
2.3 工廠方法優(yōu)缺點
2.3.1 優(yōu)點
- 在系統(tǒng)中加入新產(chǎn)品時,無須修改抽象工廠和抽象產(chǎn)品提供的接口,只要添加一個具體工廠和具體產(chǎn)品就可以了。這樣,系統(tǒng)的可擴展性也就變得非常好,更加符合 “開閉原則”。而簡單工廠模式需要修改工廠類的判斷邏輯。
- 符合單一職責的原則,即每個具體工廠類只負責創(chuàng)建對應的產(chǎn)品。而簡單工廠模式中的工廠類存在一定的邏輯判斷。
- 基于工廠角色和產(chǎn)品角色的多態(tài)性設計是工廠方法模式的關鍵。它能夠使工廠可以自主確定創(chuàng)建何種產(chǎn)品對象,而如何創(chuàng)建這個對象的細節(jié)則完全封裝在具體工廠內部。工廠方法模式之所以又被稱為多態(tài)工廠模式,是因為所有的具體工廠類都具有同一抽象父類。
2.3.2 缺點
- 在添加新產(chǎn)品時,需要編寫新的具體產(chǎn)品類,而且還要提供與之對應的具體工廠類,系統(tǒng)中類的個數(shù)將成對增加,在一定程度上增加了系統(tǒng)的復雜度,有更多的類需要編譯和運行,會給系統(tǒng)帶來一些額外的開銷。
- 一個具體工廠只能創(chuàng)建一種具體產(chǎn)品。
最后我們來簡單介紹一下工廠方法的應用場景。
2.4 工廠方法應用場景
- 一個類不知道它所需要的對象的類:在工廠方法模式中,客戶端不需要知道具體產(chǎn)品類的類名,只需要知道所對應的工廠即可,具體的產(chǎn)品對象由具體工廠類創(chuàng)建;客戶端需要知道創(chuàng)建具體產(chǎn)品的工廠類。
- 一個類通過其子類來指定創(chuàng)建哪個對象:在工廠方法模式中,對于抽象工廠類只需要提供一個創(chuàng)建產(chǎn)品的接口,而由其子類來確定具體要創(chuàng)建的對象,利用面向對象的多態(tài)性和里氏代換原則,在程序運行時,子類對象將覆蓋父類對象,從而使得系統(tǒng)更容易擴展。
三、參考資源
簡單工廠模式(SimpleFactoryPattern)
design-patterns - simple_factory
工廠方法模式(Factory Method)