歡迎您光臨本站 註冊首頁

JS 設計模式之:工廠模式定義與實現方法淺析

←手機掃碼閱讀     retouched @ 2020-05-06 , reply:0

前言

今天來說一說一種常見的設計模式:工廠模式。
工廠模式是一種創建對象的 創建型模式,遵循 DRY(Don't Repeat Yourself)原則。在該模式下,代碼將會根據具體的輸入或其他既定規則,自行決定創建哪種類型的對象。簡單點兒說就是,動態返回需要的實例對象。
回顧上次的例子
讓我們繼續使用單例模式中的例子,一個日誌工具 Logger :
class Logger { log (...args) { console.log(...args); } }
上面是最核心的 api,每次使用都需要使用 new Logger() 來創建一個 logger 對象,然後使用方法就和 console 一樣啦~
多種 Logger
假如我們現在的代碼要支持 electron 環境,即日誌既可以是 console 日誌,也可以是 file 日誌,那麼我們就需要有兩種類型的 logger:
ConsoleLogger
// logger/console.js class ConsoleLogger { log (...args) { console.log(...args) } } export default ConsoleLogger
FileLogger
// logger/file.js class FileLogger { log (...args) { dumpLog(...args) } } export default FileLogger
這裡先不用管 dumpLog 的具體實現,只用知道它就是將日誌寫在文件中的即可~
使用工廠
我們已經有了兩種類型的 logger,但是這兩種 logger 的 api 實際上都是一樣的,在項目中直接導入當然也可以使用,只不過每次都要導入對應類型的模塊,然後再使用,像下面這樣:
使用 console logger
import ConsoleLogger from './logger/console' const logger = new ConsoleLogger()
使用 file logger
import FileLogger from './logger/file' const logger = new FileLogger()
是不是很繁瑣?如果還有其他 logger 類型,如遠程日誌,就會出現更多種使用方式了。為了把 logger 模塊的使用方式統一,這時候就會用到工廠模式啦~
讓我們新建一個 index.js :
// logger/index.js import ConsoleLogger from './console.js' import FileLogger from './file.js' function createLogger(type = 'console') { if (type === 'console') { return new ConsoleLogger() } else if (type === 'file') { return new FileLogger() } throw new Error(`Logger type not found: ${type}`) } export default createLogger
好了,這下我們的使用方式就會變成這樣:
import createLogger from './logger' // console logger const logger1 = createLogger('console') // file logger const logger2 = createLogger('file')
重構一下
上面的 if else 不是很優雅?如果有更多中 logger 類型添加起來很麻煩?那我們可以使用對象來映射一下,從而拋棄 if else,同時添加一個 logger 選項。
// logger/index.js import ConsoleLogger from './console.js' import FileLogger from './file.js' const loggerMap = { console: ConsoleLogger, file: FileLogger } // 可選參數一般放在最後面 function createLogger(options, type = 'console') { const Logger = loggerMap[type] if (Logger) { return new Logger(options) } throw new Error(`Logger type not found: ${type}`) }
上面這種封裝的方式,其實也符合 SOLID 原則中的 開閉原則 ,即 對擴展開放,對修改關閉,每當我們添加一種 logger 類型時,只需要新增一個文件,然後將構造器註冊進 loggerMap 中即可。而外面的使用方式都是不變的,這樣就用最少的修改完成了功能的新增,是不是很棒呀~
總結
下面我們來回顧一下工廠模式的優點:
動態創建對象 :可以用於需要在 運行時 確定對象類型的情況。
:可以用於需要在 確定對象類型的情況。 抽象 :封裝了對象創建的細節,用戶不會接觸到對象的構造器,只需要告訴工廠需要哪種對象。
:封裝了對象創建的細節,用戶不會接觸到對象的構造器,只需要告訴工廠需要哪種對象。 可用性 / 可維護性:將相似的對象用一個工廠管理,提供統一的創建接口,滿足 開閉原則,使我們可以輕鬆添加多種類型的對象,而無需修改大量代碼。
好啦~!工廠模式就介紹到這裡啦~ 下次我們講一講裝飾器模式~


[retouched ] JS 設計模式之:工廠模式定義與實現方法淺析已經有251次圍觀

http://coctec.com/docs/javascript/show-post-233122.html