前端设计模式
浏览器设计模式
单例模式
定义:全局唯一访问对象
In software engineering, the singleton pattern is a software design patternthat restricts the instantiation of a class to one "single" instance. This is useful when exactly one object is needed to coordinate actions across the system.
应用场景:缓存、全局状态管理
1、需要频繁实例化然后销毁的对象。
2、创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
3、有状态的工具类对象。
4、频繁访问数据库或文件的对象
用单例模式实现请求缓存
static getInstance(){
if(this.instance){
return this.i;nstance;
this.instance=new Request();
return this.instance;
}
}
事例补充:弹窗、对话框、浮窗之类是使用单例模式
//创建对象的方法传入疯转的getSingle函数
var getSingle=function(fn){
var result; //这里的result只有在调用时才被创建,所以是惰性单例
return function(){
return result || (result=fn.apply(this,arguments)); //控制单例
}
};
//单一职责,这里就是创建div,getSingle做单例
var createModal=function(){
var div = document.creatElement('div');
return div
};
var createSingletModal=getSingle(createModal);
document.getElementById( 'Btn' ).onclick = function(){
var layer = createSingletModal();
layer.style.display = 'block';
};
发布订阅模式
定义:一种订阅机制,可在被订阅对象发生变化时通知订阅者。
订阅发布模式(Publish-Subscribe Pattern),又称观察者模式(Observer Pattern),是一种常用的设计模式,用于解决多个对象间的依赖关系,降低系统耦合度,提高代码的复用性和可维护性。
发布订阅是一种消息范式,发布者不会将消息直接发送给订阅者,而是将发布的消息分为不同的类别,这意味着发布者和订阅者不知道彼此的存在。在发布者和订阅者之间存在第三个组件,称为消息代理或调度中心或中间件,它维持着发布者和订阅者之间的联系,过滤所有发布者传入的消息并相应地分发它们给订阅者。订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者存在在订阅发布模式中,存在两类角色:发布者和订阅者。发布者负责向订阅者发送消息,而订阅者则负责接收消息并做出相应的处理。发布者和订阅者之间通过一个中介者(通常称为消息队列或事件总线)来进行通信,发布者发布消息后,消息将被发送到中介者,中介者再将消息分发给所有订阅者。
具体实现上,订阅者需要先订阅发布者感兴趣的事件或主题(Topic),这样才能接收到相应的消息。当发布者发布与该主题相关的消息时,所有订阅该主题的订阅者将收到该消息,并进行相应的处理。
应用场景:从系统架构之间的解耦,到业务中一些实现模式,像邮件订阅,上线订阅等
- 应用程序需要向大量消费者广播信息。例如微信订阅号就是一个消费者量庞大的广播平台。
- 应用程序需要与一个或多个独立开发的应用程序或服务通信,这些应用程序或服务可能使用不同的平台、编程语言和通信协议。
- 应用程序可以向消费者发送信息,而不需要消费者的实时响应。
发布订阅模式与观察者模式对比
观察者模式中,Subject 自己维护观察者列表进行注册和通知。
发布订阅模式的话,引入一个中间平台进行注册和通知,相当于从 Subject 中解耦出来。
观察者通过 on 向 EventBus 注册事件,然后 Subject 通过 emit 向 EventBus 发射事件,由 EventBus 来向观察者更新。
EventBus事例
const observersMap = {}
const listen = function (key, fn) {
if (!observersMap[key]) {
observersMap[key] = [];
}
observersMap[key].push(fn);
};
const trigger = function () {
const key = Array.prototype.shift.call(arguments),
fns = observersMap[key];
if (!fns || fns.length === 0) {
return false;
}
for (let i = 0, fn; fn = fns[i];i++ ) {
fn.apply(this, arguments);
}
};
const remove = function (key, fn) {
const fns = observersMap[key];
if (!fns) {
return false;
}
if (!fn) {
fns && (fns.length = 0) // 全部清空
} else {
let findIndex = -1;
for (let i = 0; i < fns.length; i++) {
if (fns[i] === fn) {
findIndex = i;
break;
}
}
if (findIndex !== -1) {
fns.splice(findIndex, 1);
}
}
};
// 同一种功能可能会见到不同名字,这里都导出去
export const EventBus = {
listen,
attach: listen,
on: listen,
remove,
detach: remove,
trigger,
emit: trigger,
};