00、基礎概念
🚩工廠模式封裝了對象的創建
new()
,將消費者(使用)和生產者(實現)解耦。
工廠是幹什麼的?工廠是生產標準規格的商品的地方,建好工廠,投入原料(參數),產出特定規格的產品。so,工廠模式就是把對象的創建 —— new()
封裝起來,在工廠裏實現對象的創建(商品的生產)。這樣做的好處是用來解耦,解耦對象的消費(使用)和創建(實現),面向抽象編程(這個用到TS中的接口類型)。
✅使用場景:
- Vue中的
createElement('h'); createElement('div')
創建虛擬Dom;vue-router 中的路由基於模式mode
創建不同的路由對象。 - 多個同類對象的創建,創建過程複雜,而使用者不用關注創建、實現過程,只管拿到實例來使用。就像我們日常到超市購買商品,只管選擇使用,不用關注商品是怎麼生產的。
生產實例(商品)的工廠可以是小作坊,只生產少量簡單的商品,也可以是大型的複雜工廠,因此基於場景複雜程度又有多個工廠模式:
類別 | 說明 |
---|---|
簡單工廠(Simple Factory) | 小作坊,適用於少量對象的創建,集中式管理,使用簡單、擴展不便 |
工廠方法(Factory Method) | 正規小工廠,每種產品一個獨立工廠,偏平化擴展 |
抽象工廠(Abstract Factory) | 集團化大廠,產品種類、層級衆多,需要多層級的工廠來管理,代碼也稍複雜 |
實際掌握簡單工廠就差不多了,工廠方法、抽象工廠瞭解下即可。
01、簡單工廠(Simple Factory)
簡單工廠模式,也稱爲靜態工廠模式(Static Factory Method),由一個(靜態)類統一管理對象的創建,,根據一個簡單參數創建不同的示例對象。針對少量的、簡單的場景,在工廠中統一實現所有商品的創建。如下示例,手機工廠提供多型號手機的創建,傳入手機型號參數即可。
示例代碼:
let HuaweiPhone = class { name = '華爲' }
let XiaomiPhone = class { name = '小米' }
// 手機生產工廠
class PhoneFactory {
static create(type) {
switch (type) {
case 'huawei':
return new HuaweiPhone()
case 'xiaomi':
return new XiaomiPhone()
default:
throw new Error(`不支持生產型號爲${type}的設備`)
}
}
}
// 使用,調用工廠方法創建對象實例
let p1 = PhoneFactory.create('xiaomi')
let p2 = PhoneFactory.create('huawei')
console.log({ p1, p2 })
上面版本代碼中,如果擴充其他型號,則需要修改工廠的代碼,不利於擴展,可以稍微改進下,支持動態新增創建對象實例的方法。
// 手機生產工廠
class PhoneFactory {
// 實例對象創建器Map
#constructors = new Map()
constructor() {
this.#constructors.set('huawei', () => new HuaweiPhone())
this.#constructors.set('xiaomi', () => new XiaomiPhone())
}
// 可擴展型號
add(type, func) {
this.#constructors.set(type, func)
}
// 生產商品
create(type) {
const func = this.#constructors.get(type)
if (func) {
return func.call()
}
throw new Error(`不支持生產型號爲${type}的設備`)
}
}
const phoneFactory = new PhoneFactory()
// 添加蘋果型號
let IPhone = class { name = '蘋果' }
phoneFactory.add('iphone', () => new IPhone())
// 使用,調用工廠方法創建對象實例
let p1 = phoneFactory.create('iphone')
let p2 = phoneFactory.create('huawei')
02、工廠方法(Factory Method)
簡單工廠是小作坊,產量有限,如果生產的型號很多,在一個地方管理所有的new()
操作,負擔很大,風險也很大。工廠方法(也叫工廠模式)就是爲每一個產品建立單獨的工廠,一個工廠只生產一類商品,這樣就可以靈活擴展,相互不影響了。
代碼示例:
let HuaweiPhone = class { name = '華爲' }
let XiaomiPhone = class { name = '小米' }
// 沒什麼用的工廠基類(JS中可以不要),用來抽象工廠接口
let IFactory = class { creat() { } }
// 華爲手機工廠
class HuaweiFactory extends IFactory {
creat() {
return new HuaweiPhone()
}
}
// 小米手機工廠
class XiaomiFactory extends IFactory {
creat() {
return new XiaomiPhone()
}
}
// 使用
const huaweiFactory = new HuaweiFactory()
let p1 = huaweiFactory.creat()
let p2 = huaweiFactory.creat()
在Java、C#語言中都會用接口進行抽象、約束,面向抽象編程,實現起來會比較清晰。JavaScript中就沒法抽象約束了,比較隨意,只能靠TypeScript了。
03、抽象工廠(Abstract Factory)
如果說簡單工廠是小作坊,工廠方法就是小工廠,那抽象工廠就是大型集團了,下屬多個產業鏈、多個工廠。
抽象工廠可以看做是簡單工廠+工廠方法的結合升級,增加了產品族的概念。還是用電子產品生產來舉例,比如一個大型電子產品工廠,有多個品牌產品,如華爲、小米,每個品牌的電子產品形成一個產品族,包含多個產品,如手機、平板、電視等等,不同品牌的產品也是不同的。因此一個產品工廠(如華爲工廠)就會有多條生產線,生產多個產品(手機、平板、電視)。
🚩基本結構:抽象工廠類+具體工廠類,抽象產品類+具體產品類組合。JS中沒有沒有抽象類、接口的概念,只能示意一下(或者TS),抽象工廠簡單瞭解即可,掌握上面的簡單工廠、工廠方法就差不多了。
示例代碼:
// 模擬手機抽象類
let IPhone = class { name = '手機' }
// 手機產品
let HuaweiPhone = class extends IPhone { name = '華爲' + this.name }
let XiaomiPhone = class extends IPhone { name = '小米' + this.name }
// 模擬電視抽象類
let ITV = class { name = '電視' }
// 電視產品
let HuaweiTV = class extends ITV { name = '華爲' + this.name }
let XiaomiTV = class extends ITV { name = '小米' + this.name }
// 模擬抽象工廠,含兩個抽象方法,生產手機、電視
let AbstractFactory = class { createPhone() { }; createTV() { } }
// 具體工廠:華爲工廠
class HuaweiFactory extends AbstractFactory {
createPhone() {
return new HuaweiPhone()
}
createTV() {
return new HuaweiTV()
}
}
// 具體工廠:小米工廠
class XiaomiFactory extends AbstractFactory {
createPhone() {
return new XiaomiPhone()
}
createTV() {
return new XiaomiTV()
}
}
// 使用
let xiaomiFactory = new XiaomiFactory()
let m1 = xiaomiFactory.createPhone();
let m2 = xiaomiFactory.createTV();
console.log(m1, m2) // XiaomiPhone {name: '小米手機'} XiaomiTV {name: '小米電視'}
參考資料
- 《Head First 設計模式 中文版》
- JavaScript Patterns
- 簡單工廠模式( Simple Factory Pattern )
©️版權申明:版權所有@安木夕,本文內容僅供學習,歡迎指正、交流,轉載請註明出處!原文編輯地址-語雀