设计模式(工厂、单例、发布/订阅、代理、策略))

设计模式

针对特定问题的简单而优雅的解决方案

工厂模式

创建对象。
使用相同的接口,创建不同的实例。

var factory = (function (){
  var cars = {
    'car1': function (){
      this.speed = '380km/h';
      this.type = '豪华版';
    },
    'car2': function (){
      this.speed = '300km/h';
      this.type = '中配版';
    }
  }

  return function (config){
    return new cars[config]();
  }
})();

var car2 = factory('car2');
var car1 = factory('car1');
console.log( car2.type );  // 中配版

单例模式

保证一个类仅有一个实例

// 常见面试题
function Fun() {
  // 在函数中添加代码,使下面的运行结果成立
  if (Fun.instance) {
    return Fun.instance;
  }
  this.attr = 'hello world';
  return Fun.instance = this;
}
// Fun.instance = 123;暴露在外部,可以能被修改,导致程序运行不正常
var obj1 = new Fun();
var obj2 = new Fun();
console.log(obj1 === obj2); //true
console.log(obj1.attr); // 'hello world'

发布/订阅模式

解决的是对象间的一种一对多的依赖关系

  • 观察:添加一个缓存列表,将发布、订阅、取消订阅、构造函数添加到原型上。
  • 发布:判断是否有type,无则return,有则遍历,回调访问。
  • 订阅:判断是否有type,无则创建空数组,有则使用push入订阅数组。
  • 取消订阅:
    (1)清空缓存列表
    (2)删除对应的type
    (3)删除对应的type的回调函数
function Observe(){
  this.cacheList = {};// 缓存列表
  // { // 列表的一个格式
  //   'houseTypeA': [fn1,fn2,fn3],
  //   'houseTypeB': [fn1,fn2,fn3,fn4]
  // }
}
Observe.prototype = {
  constructor: Observe,
  // 发布:取出对应的消息类型,执行所有回调函数传入发布的消息
  publish: function (type,message){
    if (!this.cacheList[type]){
      return;
    }
    this.cacheList[type].forEach(function (cb){
      cb(message);
    });
  },
  // 订阅:往某个消息类型中添加回调函数
  subscribe: function (type,callback){
    // 判断对象是否有type此属性
    if (!this.cacheList[type]) {
      this.cacheList[type] = [];
    }
    // 往对应的消息类型插入回调函数
    this.cacheList[type].push(callback);
  },
  // 取消订阅
  unsubscribe: function (type,callback){
    if (!type) {// 直接调用,没有任何参数
      this.cacheList = {};
    } else if (type&&!callback) {// 删除某个消息类型的所有回调函数
      delete this.cacheList[type];
    } else {// 删除某个消息类型中的某个回调函数
      this.cacheList[type] = this.cacheList[type].filter(function (cb){
        return cb !== callback;
      })
    }
  }
}

var btn1 = document.querySelector('.btn1');
var btn2 = document.querySelector('.btn2');
var send1 = document.querySelector('.send1');
var send2 = document.querySelector('.send2');

var obs = new Observe();
btn1.onclick = function (){
  console.log('订阅了houseTypeA。。。');
  obs.subscribe('houseTypeA',function (msg){
    console.log('收到的消息:'+msg);
  });
}

send1.onclick = function (){
  obs.publish('houseTypeA','订阅消息内容');
}

代理模式

为一个对象提供一个代理

var imageModule = (function (){// 本体对象
  var showimg = new Image();
  return {
    setSrc: function (dom,src){
      showimg.src = src;
      dom.appendChild(showimg);
    }
  }
})();

var proxyModule = (function (){// 代理对象
  var loadimg = new Image();
  var showDom;
  loadimg.onload = function (){
    imageModule.setSrc(showDom,this.src);
  }
  return {
    setSrc: function (dom,src){
      showDom = dom;
      loadimg.src = src;
      imageModule.setSrc(dom,'./loading.gif');
    }
  }
})();

var show = document.querySelector('.show');
imageModule.setSrc(show,'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1597310800388&di=678d9f85fc9f5b2b5ad301df43d32615&imgtype=0&src=http%3A%2F%2Fa0.att.hudong.com%2F56%2F12%2F01300000164151121576126282411.jpg');

策略模式

定义一系列算法,把它们封装起来,并且使它们可以互相替换。主要分为俩部分:
策略类,封装业务算法,把具体的计算过程封装在策略类中。
环境类(客户直接访问的类),内部把用户的需求委托给策略对象。

var strategy = {// 策略对象
  'performanceA': function (salary){
    return salary * 8;
  },
  'performanceB': function (salary){
    return salary * 5;
  },
  'performanceC': function (salary){
    return salary * 3;
  },
  'performanceD': function (salary){
    return salary * 1.2;
  }
}
var getBonus = function (level,salary){// 环境类
  return strategy[level](salary);
}
console.log( getBonus('performanceB',12000) );
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容