JavaScript设计模式
设计模式的定义:在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案
当然我们可以用一个通俗的说法:设计模式是解决某个特定场景下对某种问题的解决方案。因此,当我们遇到合适的场景时,我们可能会条件反射一样自然而然想到符合这种场景的设计模式。
比如,当系统中某个接口的结构已经无法满足我们现在的业务需求,但又不能改动这个接口,因为可能原来的系统很多功能都依赖于这个接口,改动接口会牵扯到太多文件。因此应对这种场景,我们可以很快地想到可以用适配器模式来解决这个问题。
下面介绍几种在JavaScript中常见的几种设计模式:
1.单例模式
单例模式的定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点。实现的方法为先判断实例存在与否,如果存在则直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。
适用场景:一个单一对象。比如:弹窗,无论点击多少次,弹窗只应该被创建一次。
class CreateUser {
constructor(name) {
this.name = name;
this.getName();
}
getName() {
return this.name;
}
}
// 代理实现单例模式
var ProxyMode = (function() {
var instance = null;
return function(name) {
if(!instance) {
instance = new CreateUser(name);
}
return instance;
}
})();
// 测试单体模式的实例
var a = new ProxyMode("aaa");
var b = new ProxyMode("bbb");
// 因为单体模式是只实例化一次,所以下面的实例是相等的
console.log(a === b); //true
2.中介者模式
中介者模式的定义:通过一个中介者对象,其他所有的相关对象都通过该中介者对象来通信,而不是相互引用,当其中的一个对象发生改变时,只需要通知中介者对象即可。通过中介者模式可以解除对象与对象之间的紧耦合关系。
例如:现实生活中,航线上的飞机只需要和机场的塔台通信就能确定航线和飞行状态,而不需要和所有飞机通信。同时塔台作为中介者,知道每架飞机的飞行状态,所以可以安排所有飞机的起降和航线安排。
中介者模式适用的场景:例如购物车需求,存在商品选择表单、颜色选择表单、购买数量表单等等,都会触发change事件,那么可以通过中介者来转发处理这些事件,实现各个事件间的解耦,仅仅维护中介者对象即可。
var goods = { //手机库存
'red|32G': 3,
'red|64G': 1,
'blue|32G': 7,
'blue|32G': 6,
};
//中介者
var mediator = (function() {
var colorSelect = document.getElementById('colorSelect');
var memorySelect = document.getElementById('memorySelect');
var numSelect = document.getElementById('numSelect');
return {
changed: function(obj) {
switch(obj){
case colorSelect:
//TODO
break;
case memorySelect:
//TODO
break;
case numSelect:
//TODO
break;
}
}
}
})();
colorSelect.onchange = function() {
mediator.changed(this);
};
memorySelect.onchange = function() {
mediator.changed(this);
};
numSelect.onchange = function() {
mediator.changed(this);
};
中介者模式就是用来帮助我们把复杂的层级关系铺平为一对多的简单关系
使用中介者模式以后,可以帮助我们让原本按照树型结构传递的数据可以转换为平级的结构(本来数据就不像组件需要有树型关系)
3.发布-订阅模式
发布-订阅模式广泛应用于异步编程中,这是一种替代传递回调函数的方案。
现实中的例子:
小明想买房,到了售楼处被告知,该楼盘的房子早已售罄。售楼MM告诉小明,不久后还有一些尾盘推出,时间还未定。
小明记下了售楼处的电话,以后每天都会打电话询问是否可购买。除了小明,还有小红、小强也会每天向售楼处咨询这个问题。可能售楼处每天回答 1000个相同内容的电话。
当然现实中销售公司会一一将客户的电话记录下来,新楼盘推出的时候,售楼 MM会翻开花名册,遍历上面的电话号码,依次发送一条短信来通知他们。
发布 - 订阅模式的作用
购房者不用再天天给售楼处打电话咨询开售时间,在合适的时间点,售楼处作为发布者会通知这些消息订阅者。
购房者和售楼处之间不再强耦合在一起,当有新的购房者出现时,他只需把手机号码留在售楼处,售楼处不关心购房者的任何情况。 而售楼处的变动也不会影响购买者,比如售楼 MM 离职,这些改变都跟购房者无关,只要售楼处记得发短信这件事情。
发布订阅模式可以取代对象之间硬编码的通知机制,一个对象不用再显式地调用另一个对象的某个接口,让两个对象低耦合地联系在一起。
4.发布-订阅和观察者模式的区别
观察者模式和发布订阅模式最大的区别就是发布订阅模式有个事件 调度中心!!!
image.png
观察者模式中观察者和目标直接进行交互,而发布订阅模式中统一由 调度中心 进行处理,订阅者和发布者 互不干扰 。这样一方面实现了 解耦,还有就是可以实现更细粒度的一些控制。比如发布者发布了很多消息,但是不想所有的订阅者都接收到,就可以在 调度中心 做一些处理,类似于 权限控制之类的。
为方便记忆,关键字:调度中心、解耦(发布/订阅者互不干扰)
vue源码中使用的是发布订阅模式
5.发布-订阅和中介者模式的区别
有些人可能会觉得这两个模式很像,比如说我,现在来理一理
这两个很像
华丽分割线----------------------------------------------------------------------------------------------------------------------------------------------------------
观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。bus.$emit属于观察者模式
中介者模式(Mediator Pattern)定义:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,它是一种对象行为型模式。
观察者模式规定发布者与订阅者是同步的,发布者发布信息,就立刻通知对应的订阅者,而发布订阅模式,发布者与订阅者是通过一个叫消息代理的中间件,进行消息传递的,也就是说发布者与订阅者相互互不相知,这时当有多个消息同时传递时,消息将存放在消息队列里,是异步的。