发布-订阅模式发布-订阅模式是指对象(Subscriber)希望通过自定义事件订阅主题接收基于某个主题的通知,对象(Publisher)被事件激活发布主题事件通知订阅主题的每个订阅者对象。constfs=require('fs')letevents={arr:[],on(callback){this.arr.push(callback)},emit(){this.arr.forEach(fn=>fn())}}events.on(function(){console.log('Subscribe');//订阅事件})fs.readFile('./demo1.txt','utf8',function(err,data){events.emit();//问题})fs.readFile('./demo2.txt','utf8',function(err,data){events.emit();//问题})先看一个简单的例子:定义一个对象events,带有一个arr属性来存放要执行的回调数组;on和emit用于定义订阅和发布的方法。events.on()定义了订阅方法,将要执行的函数存储在一个数组中;events.emit()做的是发布行为,每次发布都会执行events.on中的回调,所以上面代码执行结果为://订阅//订阅然后修改回调的参数,并在发布时传入读取的数据:fs.readFile('./demo1.txt','utf8',function(err,data){events.emit(data);})fs.readFile('./demo2.txt','utf8',function(err,data){events.emit(data);})在events中添加dataSource属性,存储数据源:letevents={dataSource:[],arr:[],on(callback){this.arr.push(callback)},emit(data){this.dataSource.push(data);this.arr.forEach(fn=>fn(this.dataSource))}}这样做的目的是控制订阅时的数据:events.on(function(data){if(data.length===2){console.log('subscription',data);//订阅事件}})publish和subscribe一般都是用来解耦的,主要是基于回调函数。您不能订阅,只能发布;发布和订阅是分开的,两者之间没有关系。整个代码如下:constfs=require('fs')letevents={dataSource:[],arr:[],on(callback){this.arr.push(callback)},emit(data){this.dataSource.push(data)this.arr.forEach(fn=>fn(this.dataSource))}}events.on(function(data){console.log('subscribe',data);//订阅events})fs.readFile('./demo1.txt','utf8',function(err,data){events.emit(data);})fs.readFile('./demo2.txt','utf8',function(err,data){events.emit(data);})观察者模式观察者模式是存储状态变化,当被观察对象的状态发生变化时,会一一向观察者发送通知。classSubject{//目标对象classconstructor(name){this.name=name;这个.state=1;这个.arr=[];}attach(){this.arr.push(o);}setState(state){this.state=state;this.arr.forEach(o=>o.updateState(state))}}classObserver{//observerclassconstructor(name){this.name=name;}updateState(state){console.log(this.name+'接收到的状态变化是:'+state)}}lets=newSubject();leto1=newObserver('Observer1');leto2=new观察者('观察者2');s.attach(o1);//被观察的目标对象注册观察者s.attach(o2);s.setState(2);//通知所有观察者,状态改变//输出结果观察者1收到状态改变:2观察者2收到状态改变:2观察者和被观察者关联;观察者必须放在被观察者的数组中。Vue基于观察者模式。当某个数据发生变化时,会通知视图进行更新;另外,观察者模式实际上包括发布和订阅模式。工厂模式工厂模式是创建对象最常用的设计模式之一。它没有暴露创建对象的具体逻辑,而是将逻辑封装在一个函数中,那么这个函数就可以看成是一个工厂。简单工厂letFactory=function(role){functionAdmin(){this.name='SuperAdministrator';this.authority=['首页','产品列表','产品详情','用户管理','权限管理'];}functionManager(){this.name='Administrator';this.authority=['首页','产品列表','产品详情','用户管理'];}functionUser(){this.name='普通用户';this.authority=['首页','产品列表','产品详情'];}switch(role){case'Admin':returnnewAdmin();case'Manager':returnnewManager();case'User':returnnewUser();default:thrownewError('参数错误,请选择:Admin,Manager,User');}}letadmin=Factory('Admin');letmanager=Factory('经理');letuser=Factory('用户');通过判断传递的参数返回不同的对象实例,但这三个实例的内部结构非常相似,所以也可以对其进行优化。工厂方法工厂方法的初衷是将对象的实际创建推迟到子类中,使核心类成为抽象类。在工厂函数的原型中设置所有对象的构造函数,方便后期扩展。letFactory=function(role){//安全模式创建工厂方法函数if(thisinstanceofFactory){letf=newthis[role]();返回f;}else{返回新工厂(角色);}}//工厂方法原型设置对象构造函数Factory.prototype={Admin:function(){this.name='SuperAdmin';this.authority=['首页','产品列表','产品详情','用户管理','权限管理'];},经理:function(){this.name='Administrator';this.authority=['首页','产品列表','产品详情','用户管理'];},User:functionUser(){this.name='普通用户';this.authority=['首页','产品列表','产品详情'];}}letadmin=Factory('Admin');letmanager=Factory('Manager');letuser=Factory('User');在调用上面函数的过程中,一旦在任何阶段忘记使用new运算符,就会无法获取到实例,但是使用安全模式Instantiation可以很好的解决这个问题。
