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

设计模式

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

工厂模式

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

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) );
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,585评论 4 365
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,923评论 1 301
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,314评论 0 248
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,346评论 0 214
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,718评论 3 291
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,828评论 1 223
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,020评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,758评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,486评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,722评论 2 251
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,196评论 1 262
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,546评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,211评论 3 240
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,132评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,916评论 0 200
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,904评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,758评论 2 274

推荐阅读更多精彩内容