# 设计模式

# 单例模式

class SingletonLogin {
  constructor(name, password) {
    this.name = name;
    this.password = password;
  }

  static getInstance(name, password) {
    // 判断对象是否已经被创建,若创建则返回对象
    if (!this.instance) this.instance = new SingletonLogin(name, password);
    return this.instance;
  }
}
let obj1 = SingletonLogin.getInstance('CXK','123');
let obj2 = SingletonLogin.getInstance('CXK','321');

console.log(obj1===obj2);    // true
console.log(obj1);           // {name:CXK,password:123}
console.log(obj2);           // 输出的依然是{name:CXK,password:123}

# 装饰器模块

function info(target) {
  target.prototype.name = 'san';
  target.prototype.age = 10;
}
@info
class Man {}
let man = new Man();
man.name; // san

# 适配器模式

class Adaptte {
  test() {
    return 'old interface';
  }
}

class Target {
  constructor() {
    this.adaptee = new Adaptte();
  }
  test() {
    let info = this.adaptee.test();
    return `设配${info}`;
  }
}

# 代理模式

const idol = {
  name: 'some',
  phone: '123',
  price: 10000
};

const agent = new Proxy(idol, {
  get: function(target) {
    // 拦截明星电话的请求,只提供经纪人的电话
    return '经纪人电话';
  },
  set: function(target, key, value) {
    if (key === 'price') {
      // 经纪人过滤资质
      if (value < target.price) throw new Error('报价过低');
      target.price = value;
    }
  }
});
agent.phone;        //经纪人电话:10010
agent.price = 100;  //Uncaught Error: 报价过低

# 工厂模式

class User {
  constructor(name, auth) {
    this.name = name;
    this.auth = auth;
  }
}

class UserFactory {
  static createUser(name, auth) {
    // 工厂内部封装了创建对象的逻辑
    // 权限为admin时, auth = 1, 权限为user时, auth为2
    // 使用者在外部创建对象时,不需要知道各个权限对应哪个字段,不需要知道赋权的逻辑,只需要知道创建了一个管理员和用户
    if (auth === 'admin') new User(name, 1);
    if (auth === 'user') new User(name, 2);
  }
}

const admin = UserFactory.createUser('cxk', 'admin');
const user = UserFactory.createUser('cxk', 'user');

# 观察者

class Observer {
  constructor(fn) {
    this.update = fn;
  }
}

// 被观察者
class Subject {
  constructor() {
    this.observers = []; // 观察者队列
  }

  addObserver(observer) {
    this.observers.push(observer); // 往观察者队列添加观察者
  }

  notify() { // 通知所有观察者,实际时把观察者的update()都执行一遍
    this.observers.forEach(observer => {
      observer.update(); // 依次取出观察者,并执行观察者的update方法
    });
  }
}