js设计模式---工厂模式

1.痛点
eg:A类中实例化B类。如果B的构造函数发生更改,如果b引用次数很多。
2.利
构造方法代替new,
减少冗余代码。

3.分类

  • 简单工厂模式

    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` 的判断逻辑代码就变得臃肿起来,难以维护。
*   不适用创建多类对象
  • 工厂方法模式

将实际创建对象工作推迟到子类当中,核心类就成了抽象类。这样添加新的类时就无需修改工厂方法,只需要将子类注册进工厂方法的原型对象中即可。

  // 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()
  • 抽象工厂模式

抽象工厂只留对外的口子,不做事,留给外界覆盖(子类重写接口方法以便创建的时候指定自己的对象类型)。主要用于对产品类簇的创建,不直接生成实例(简单工厂模式和工厂方法模式都是生成实例)。

  • 抽象类是一种声明但不能使用的类,子类必须先实现其方法才能调用;
  • 可以在抽象类中定义一套规范,供子类去继承实现;
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())

你可能感兴趣的:(javascript,设计模式)