前提:
在翻阅资料的时候,有人把观察者(Observer)模式等同于发布(Publish)/订阅(Subscribe)模式,也有人认为这两种模式仍是存在差别,而我认为确实是存在差别的,本质上的区别是调度的地方不一样。可是由于后者是前者发展变异而来,故而列到一篇博客中html
观察者模式
比较概念的解释是,目标和观察者是基类,目标提供维护观察者的一系列方法,观察者提供更新接口。具体观察者和具体目标继承各自的基类,而后具体观察者把本身注册到具体目标里,在具体目标发生变化时候,调度观察者的更新方法。前端
由于前端语言纷繁复杂,下边我分别举出es五、es六、ts版本java
ts版本程序员
/*** * 抽象被观察者接口 * 声明了添加、删除、通知观察者方法 */ public interface Observerable { registerObserver(o:Observer); removeObserver(o:Observer):; notifyObserver(); } /*** * 抽象观察者 * 定义了一个update()方法,当被观察者调用notifyObservers()方法时,观察者的update()方法会被回调。 */ public interface Observer { update( message:string); } /** * 被观察者,也就是微信公众号服务 * 实现了Observerable接口,对Observerable接口的三个方法进行了具体实现 */ public class WechatServer implements Observerable { private list:Observer[]; private message:string; constructor(){ this.list = []; } public registerObserver(o: Observer) { this.list.push(o) } public removeObserver(o: Observer) { for (var i=0; i < this.list.length; i++){ if (this.list[i] === o){ this.list.splice(i, 1); break; } } } public notifyObserver() { for(let i = 0; i < this.list.length; i++) { let oserver = this.list[i]; oserver.update(this.message); } } public setInfomation(s:string) { this.message = s; console.log(`微信服务更新消息:${s}`); //消息更新,通知全部观察者 this.notifyObserver(); } } /** * 观察者 */ public class User implements Observer { private name:string; private message:string; constructor(name:string) { this.name = name; } public update(message:string) { this.message = message; this.read(); } public read() { console.log(`${this.name}收到推送消息:${this.message}`); } } /** * 咱们来测试 */ let server = new WechatServer(); let userZhang = new User("张三"); let userLi = new User("李四"); let userWang = new User("王五"); server.registerObserver(userZhang); server.registerObserver(userLi); server.registerObserver(userWang); server.setInfomation("PHP是世界上最好用的语言!"); console.log("-----用户张三看到消息后颇为震惊,果断取消订阅,这时公众号又推送了一条消息,此时用户ZhangSan已经收不到消息,其余用户仍是正常能收到推送消息----------------"); server.removeObserver(userZhang); server.setInfomation("JAVA是世界上最好用的语言!"); /** * 总结:这个是ts去写的,由于用js写,我以为理解起来很费劲,哪怕是es2018!编译后可能就是你想要的版本吧 * 这个模式是典型的观察者模式,而非变异后的发布-订阅模式,二者有关联,可是并不同 * 其实前边两个接口是能够不用定义的,可是接口就是用来作规范的,之后可能不仅有微信服务,还有新闻订阅、小程序订阅、iphoneXR订购等等 * 这个模式是松偶合的。改变主题或观察者中的一方,另外一方不会受到影像 * 参考自java设计模式:https://www.cnblogs.com/luohanguo/p/7825656.html */
es5版本
写完以后,忽然发现,这尼玛不就是ts编译后的代码嘛,那两个抽象类的做用仅仅用在编译阶段,编译后的代码并不存在相关接口代码,哦!原来ts是这么个机制es6
/** * 被观察者,也就是微信公众号服务 */ var WechatServer = (function () { function WechatServer() { this.list = []; } WechatServer.prototype.registerObserver = function (o) { this.list.push(o); }; WechatServer.prototype.removeObserver = function (o) { for (var i = 0; i < this.list.length; i++) { if (this.list[i] === o) { this.list.splice(i, 1); break; } } }; WechatServer.prototype.notifyObserver = function () { for (var i = 0; i < this.list.length; i++) { var oserver = this.list[i]; oserver.update(this.message); } }; WechatServer.prototype.setInfomation = function (s) { this.message = s; console.log(`微信服务更新消息:${s}`); //消息更新,通知全部观察者 this.notifyObserver(); }; return WechatServer; }()); /** * 观察者 */ var User = (function () { function User(name) { this.name = name; } User.prototype.update = function (message) { this.message = message; this.read(); }; User.prototype.read = function () { console.log(`${this.name}收到推送消息:${this.message}`); }; return User; }()); /** * 咱们来测试 */ let server = new WechatServer(); let userZhang = new User("张三"); let userLi = new User("李四"); let userWang = new User("王五"); server.registerObserver(userZhang); server.registerObserver(userLi); server.registerObserver(userWang); server.setInfomation("PHP是世界上最好用的语言!"); console.log("-----用户张三看到消息后颇为震惊,果断取消订阅,这时公众号又推送了一条消息,此时用户ZhangSan已经收不到消息,其余用户仍是正常能收到推送消息----------------"); server.removeObserver(userZhang); server.setInfomation("JAVA是世界上最好用的语言!");
es6版本
经过这个能够了解到,由于目前包括es2018还没有实现接口、抽象功能,故而没法定义观察者约束性接口,而后还知道了,es6只是语法糖,相似于ts同样,建立类,其实本质就是es5 混合继承知识点:属性用构造,公共函数放在原型对象上,这样全部实例在内存共享一个方法,节省内存,说远了,哈哈不说了,贴代码面试
/** * 被观察者,也就是微信公众号服务 */ class WechatServer{ constructor(){ this.list = []; } registerObserver(o) { this.list.push(o); }; removeObserver(o){ for (var i = 0; i < this.list.length; i++) { if (this.list[i] === o) { this.list.splice(i, 1); break; } } } notifyObserver() { for (var i = 0; i < this.list.length; i++) { var oserver = this.list[i]; oserver.update(this.message); } } setInfomation(s){ this.message = s; console.log(`微信服务更新消息:${s}`); //消息更新,通知全部观察者 this.notifyObserver(); } } /** * 观察者 */ class User{ constructor(name) { this.name = name; } update(message) { this.message = message; this.read(); }; read (){ console.log(`${this.name}收到推送消息:${this.message}`); }; }; /** * 咱们来测试 */ let server = new WechatServer(); let userZhang = new User("张三"); let userLi = new User("李四"); let userWang = new User("王五"); server.registerObserver(userZhang); server.registerObserver(userLi); server.registerObserver(userWang); server.setInfomation("PHP是世界上最好用的语言!"); console.log("-----用户张三看到消息后颇为震惊,果断取消订阅,这时公众号又推送了一条消息,此时用户ZhangSan已经收不到消息,其余用户仍是正常能收到推送消息----------------"); server.removeObserver(userZhang); server.setInfomation("JAVA是世界上最好用的语言!");
最后再想哔哔两句:
ts和es6都是语法糖,因此面试的人会问你编译以后会是啥样,挺操dan的,由于java历来不会问我编译后的字节码是什么样
ts跟es6比,就拿这个来讲,可使用接口来约束观察者,防止程序员乱写,能够用数据类型来约束各类参数和返回值,防止乱传,等到了运行再报错,代码我都写了几千行了,谁tm找获得啊。大致来讲ts语法约束性较强,是强数据类型语言了,不少错编译阶段就会报错!小程序