js設計模式---工廠模式

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())
相關文章
相關標籤/搜索