设计模式
针对特定问题的简单而优雅的解决方案
工厂模式
创建对象。
使用相同的接口,创建不同的实例。
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) );