1.痛點
eg:A類中實例化B類。若是B的構造函數發生更改,若是b引用次數不少。
2.利
構造方法代替new,
減小冗餘代碼。緩存
3.分類iphone
簡單工廠模式函數
class SampleFactory { constructor(opt) { this.role = opt.role; this.permissions = opt.permissions; } // 靜態方法 static create(role) { switch (role) { case 'admin': return new SampleFactory({ role: '管理員', permissions: ['設置', '刪除', '新增', '建立', '開發', '推送', '提問', '評論'] }); break; case 'developer': return new SampleFactory({ role: '開發者', permissions: ['開發', '推送', '提問', '評論'] }); break; default: throw new Error('參數只能爲 admin 或 developer'); } } show() { const str = `是一個${this.role}, 權限:${this.permissions.join(', ')}`; console.log(str); } } // 實例 const xm = SampleFactory.create('admin'); xm.show(); const xh = SampleFactory.create('developer'); xh.show(); const xl = SampleFactory.create('guest'); xl.show();
- 1.簡單工廠函數適用場景 * 正確傳參,就能夠獲取所須要的對象,無需知道內部實現細節; * 內部邏輯(工廠函數)經過傳入參數判斷實例化仍是使用哪些類; * 建立對象數量少(穩定),對象的建立邏輯不復雜; 2.簡單工廠函數不適用場景 * 當須要添加新的類時,就須要修改工廠方法,這違背了開放封閉原則(OCP, 對擴展開放、對源碼修改封閉)。正所謂成也蕭何敗也蕭何。函數 `create` 內包含了全部建立對象(構造函數)的判斷邏輯代碼,若是要增長新的構造函數還須要修改函數 `create`(判斷邏輯代碼),當可選參數 `role` 變得更多時,那函數 `create` 的判斷邏輯代碼就變得臃腫起來,難以維護。 * 不適用建立多類對象
將實際建立對象工做推遲到子類當中,核心類就成了抽象類。這樣添加新的類時就無需修改工廠方法,只須要將子類註冊進工廠方法的原型對象中便可。this
// 0.0.2/function.factory.js class FunctionFactoryBase { // 抽象類 constructor(role) { if (new.target === FunctionFactoryBase) { throw new Error('抽象類不能實例'); } this.role = role; } } class FunctionFactory extends FunctionFactoryBase { // 子類 constructor(role) { super(role); } static create(role) { switch (role) { case 'admin': return new FunctionFactory({ role: '管理員', permissions: ['設置', '刪除', '新增', '建立', '開發', '推送', '提問', '評論'] }); break; case 'developer': return new FunctionFactory({ role: '開發者', permissions: ['開發', '推送', '提問', '評論'] }); break; default: throw new Error('參數只能爲 admin 或 developer'); } } show() { const { role, permissions } = this.role; const str = `是一個${role}, 權限:${permissions.join(', ')}`; console.log(str) } } // let xl = new FunctionFactoryBase(); // 此行會報錯,註釋後方可正常執行後面 let xm = FunctionFactory.create('admin'); xm.show() let xh = FunctionFactory.create('developer'); xh.show() let xl = FunctionFactory.create('guest'); xl.show()
抽象工廠只留對外的口子,不作事,留給外界覆蓋(子類重寫接口方法以便建立的時候指定本身的對象類型)。主要用於對產品類簇的建立,不直接生成實例(簡單工廠模式和工廠方法模式都是生成實例)。prototype
function AbstractFactory(subType, superType) { if (typeof AbstractFactory[superType] === 'function') { //緩存類 function F() { } //繼承父類屬性和方法 F.prototype = new AbstractFactory[superType](); //將子類 constructor 指向子類(本身) subType.prototype.constructor = subType; //子類原型繼承緩存類(父類) subType.prototype = new F(); } else { //不存在該抽象類拋出錯誤 throw new Error('抽象類不存在') } AbstractFactory.Phone = function () { this.type = 'Phone'; } AbstractFactory.Phone.prototype = { showType: function () { return new Error('Phone 抽象方法 showType 不能調用'); }, showPrice: function () { return new Error('Phone 抽象方法 showPrice 不能調用'); }, showColor: function () { return new Error('Phone 抽象方法 showColor 不能調用'); } } AbstractFactory.Pad = function () { this.type = 'Pad'; } AbstractFactory.Pad.prototype = { showType: function () { return new Error('Pad 抽象方法 showType 不能調用'); }, showPrice: function () { return new Error('Pad 抽象方法 showPrice 不能調用'); }, showColor: function () { return new Error('Pad 抽象方法 showColor 不能調用'); } } function Iphone(type, price, color) { this.type = type; this.price = price; this.color = color; } AbstractFactory(Iphone, 'Phone'); Iphone.prototype.showType = function () { return this.type; } Iphone.prototype.showPrice = function () { return this.price; } Iphone.prototype.showColor = function () { return this.color; } function Ipad(type, price, color) { this.type = type; this.price = price; this.color = color; } AbstractFactory(Ipad, 'Pad'); Ipad.prototype.showType = function () { return this.type; } Ipad.prototype.showPrice = function () { return this.price; } Ipad.prototype.showColor = function () { return this.color; } var iphone5s = new Iphone('iphone 5s', 3000, '白色'); console.log('今天剛買了' + iphone5s.showType() + ',價格是' + iphone5s.showPrice() + ',' + iphone5s.showColor()) var iphone8s = new Iphone('iphone 8s', 8000, '白色'); console.log('今天剛買了' + iphone8s.showType() + ',價格是' + iphone8s.showPrice() + ',' + iphone8s.showColor()) var ipad = new Ipad('ipad air', 2000, '騷紅色'); console.log('今天剛買了' + ipad.showType() + ',價格是' + ipad.showPrice() + ',' + ipad.showColor())