JavaScript设计模式的作用 - 提高代码的重用性,可读性,使代码更容易的维护和扩展。
确保一个类仅有一个实例,并提供一个访问它的全局访问点。一般我们是这样实现单例的,用一个变量来标志当前的类已经创建过对象,如果下次获取当前类的实例时,直接返回之前创建的对象即可
单例模式下对象只会实例化一次,我们可以利用闭包,当该对象已经存在的时候,直接返回该对象,否则重新创建
var singleton = function( fn ){
var result;
return function(){
return result || ( result = fn .apply( this, arguments ) );
}
}
var createMask = singleton( function(){
return document.body.appendChild( document.createElement('div') );
})
http://www.alloyteam.com/2012/10/common-javascript-design-patterns/
提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。
工厂就是把成员对象的创建工作转交给一个外部对象,好处在于消除对象之间的耦合(何为耦合?就是相互影响)。通过使用工厂方法而不是new关键字及具体类,可以把所有实例化的代码都集中在一个位置,有助于创建模块化的代码,这才是工厂模式的目的和优势。
能解决多个相似的问题,但不能知道对象识别的问题(对象的类型不知道)
使用工厂模式生成xhr
var XMLHttpFactory =function(){}; //这是一个简单工厂模式
XMLHttpFactory.createXMLHttp =function(){
var XMLHttp = null;
if (window.XMLHttpRequest){
XMLHttp = new XMLHttpRequest()
}elseif (window.ActiveXObject){
XMLHttp = new ActiveXObject("Microsoft.XMLHTTP")
}
return XMLHttp;
}
//XMLHttpFactory.createXMLHttp()这个方法根据当前环境的具体情况返回一个XHR对象。
var AjaxHander =function(){
var XMLHttp = XMLHttpFactory.createXMLHttp();
...
}
将其成员对象的实列化推迟到子类中,子类可以重写父类接口方法以便创建的时候指定自己的对象类型。 父类就变成了一个抽象类,但是父类可以执行子类中相同类似的方法,具体的业务逻辑需要放在子类中去实现。
定义函数实现子类继承父类,然后子类重写父类中的抽象方法。
工厂中定义多个抽象类,实现具体子类继承抽象类
实现方式—>https://segmentfault.com/a/1190000012422055
定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换
使用策略模式重构代码,可以消除程序中大片的条件分支语句。在实际开发中,我们通常会把算法的含义扩散开来,使策略模式也可以用来封装一系列的“业务规则”。只要这些业务规则指向的目标一致,并且可以被替换使用,我们就可以使用策略模式来封装他们
普通模式
var awardS = function (salary) {
return salary * 4
};
var awardA = function (salary) {
return salary * 3
};
var awardB = function (salary) {
return salary * 2
};
var calculateBonus = function (level, salary) {
if (level === 'S') {
return awardS(salary);
}
if (level === 'A') {
return awardA(salary);
}
if (level === 'B') {
return awardB(salary);
}
};
calculateBonus('A', 10000);
策略模式
var strategies = {
'S': function (salary) {
return salary * 4;
},
'A': function (salary) {
return salary * 3;
},
'B': function (salary) {
return salary * 2;
}
}
var calculateBonus = function (level, salary) {
return strategies[level](salary);
}
calculateBonus('A', 10000);
模板方法模式使用了原型链的方法,封装性好,复用性差
模板方法模式由二部分组成,第一部分是抽象父类,第二部分是具体实现的子类,一般的情况下是抽象父类封装了子类的算法框架,包括实现一些公共方法及封装子类中所有方法的执行顺序,子类可以继承这个父类,并且可以在子类中重写父类的方法,从而实现自己的业务逻辑。
模板方法是基于继承的设计模式,可以很好的提高系统的扩展性。 java中的抽象父类、子类
模板方法有两部分结构组成,第一部分是抽象父类,第二部分是具体的实现子类。
实现:父类定义方法,子类实现方法(抽象工厂模式封装了继承函数)。
示例---->https://blog.csdn.net/ligang2585116/article/details/50365276
职责链,一系列可能处理请求的对象被连接成一条链,请求在这些对象之间依次传递,直到遇到一个可以处理它的对象,减少了很多重复代码。
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
https://div.io/topic/1800#1职责链模式的定义
发布订阅模式,顾名思义,就是一个发布消息,一个监听消息,当有消息接收时处理消息。
function Publisher(name) {
this.name = '报纸' + name
// 订阅了本出版社的读者列表
this.subscribers = [];
}
// 添加一个迭代方法,遍历所有投递列表
Publisher.prototype.deliver = function(data) {
// 遍历当前出版社对象所有的订阅过的方法
const context = this
this.subscribers.forEach(function(fn) {
//data用于传参数给内部方法
fn.fire(context.name, data);
});
return this;
}
// 观察者
function Observe(callback) {
this.fire = callback;
}
// 给予订阅者阅读的能力
Observe.prototype.subscribe = function(publisher) {
var that = this;
// some如果有一个返回值为true则为true
var alreadyExists = publisher.subscribers.some(function(el){
// 这里的el指的是函数对象
return el.fire === that.fire // 查看是否已经订阅了,如果订阅了就不再订阅
});
// 如果存在这个函数对象则不进行添加
if (!alreadyExists) {
publisher.subscribers.push(this);
}
return this;
};
// 给予观察者退订的能力
Observe.prototype.unsubscribe = function(publisher) {
var that = this;
// 过滤,将返回值为true的重组成数组
publisher.subscribers = publisher.subscribers.filter(function(el) {
// 这里的el.fire指的是观察者传入的callback
// that.fire就是当前对象对callback的引用
return !(el.fire === that.fire) // 删除掉订阅
})
return this;
};
var publisher1 = new Publisher('xixi');
// 实例化的读者,这个需要改进
var observer1 = new Observe(function(publisher, text) {
console.log('得到来自'+publisher +'的订阅消息:'+ text + ',哈哈哈')
});
var observer2 = new Observe(function(publisher, text) {
console.log('得到来自'+publisher +'的订阅消息:'+ text + ',嘻嘻嘻')
});
// 读者订阅了一家报纸,在报社可以查询到该读者已经在订阅者列表了,
// publisher1.subscribers->[observer1]
observer1.subscribe(publisher1);
observer2.subscribe(publisher1)
// 分发报纸,执行所有内在方法
publisher1.deliver(13);// 输出123
// 退订
observer1.unsubscribe(publisher1);
publisher1.deliver(12388);
适配器模式(Adapter)是将一个类(对象)的接口(方法或属性)转化成客户希望的另外一个接口(方法或属性),适配器模式使得原本由于接口不兼容而不能一起工作的那些类(对象)可以一些工作。
https://segmentfault.com/a/1190000012436538
代理模式的定义是把对一个对象的访问, 交给另一个代理对象来操作.
保护代理、虚拟代理(图片预加载)、缓存代理
https://juejin.im/post/5a68491cf265da3e5661b342#heading-0