对js中观察者模式的一点理解
在观察者模式中, 当被观察者做出某动作时, 会通知关注它的观察者, 观察者收到通知后会做出相应的动作. 以歌星和粉丝为例, 歌星具有唱歌发布唱片的职能, 当歌星发布唱片时会通知关注他的粉丝们,粉丝们收到通知以后会做出相应的反应(购买唱片或是不买, 还上网收听, 由粉丝自己决定), 在这个过程中, 歌星只具有唱歌并通知他的粉丝的的职能, 而粉丝们则只能收到消息后做出自己的反应(购买或是不买, 自己决定), 这就是所谓的单一职责原则,由于明星和粉丝之间的联系只有通知,没有其他的关联, 大大降低了两者之间的耦合, 这就是解耦
首先定义一个明星类, 并创建一个集合来存储关注他的粉丝
1 | var Star = function() { // 明星 |
该明星具有唱歌的职能, 唱歌时需要通知关注他的粉丝们(会调用粉丝们的action方法)
1 | Star.prototype = { |
创建粉丝类
1 | var Fans = function() { // 粉丝 |
粉丝具有关注哪个明星的功能(把自己加入所关注明生的粉丝列表中), 也有收到明星消息后作出反应的功能
1 | Fans.prototype = { |
创建一个明星s
1 | var s = new Star(); |
创建一个粉丝f1并关注明星s, 同时定义该粉丝收到消息后会做出什么样的动作
1 | var f1 = new Fans(); |
再创建一个粉丝f2
1 | var f2 = new Fans(); |
明星发布唱片(看来此明星是华仔)
1 | s.song('一起走过的日子'); |
而在js中最经典的应用就是对事件的处理, 包括浏览器原生事件和自定义事件
以jq为便, 页面中有一个id为btn 的button, 通过jq为该按钮添加监听事件
1 | $('#btn').on('click', function(e) { |
然后通过程序触发
1 | $('#btn').trigger('click'); |
可能有人会有疑问, 在这里, 到底谁是观察者, 谁是被观察者呢?
因为在多数教程中, 观察者和被观察者往往是被设计的很分明的, 比如定义一个被观察者的类或对象, 具有发布消息的功能, 再定义一个观察者的类或对象, 具有接受被观察者通知并做出反应的功能, 在这里,两者的定义是非常明确的, 很好理解,但是在上面的这个jq的例子中, 到底谁是观察者, 谁又是被观察者呢?
我们先来看下观察者, 观察者, 首先要有订阅的功能, 反映在这里就是监听click事件什么时候被触发, 那在这里, 谁在监听呢, jq中的on是添加监听的意思, 所以执行on方法的对象就是观察者, 即btn按钮.
谁又是被观察者呢? 我们再来看下被观察者的功能,被观察者具有发布通知的功能,反映在这里就是触发click事件,而触发click事件的方法的执行者,又是$(‘#btn’)! 所以,在这里,观察者和被观察者都是按钮本身,按钮扮演着观察者和被观察者两个角色,监听事件的时候,按钮是观察者,触发事件的时候,按钮是被观察者,这正是事件处理中观察者模式与其他地方不一样的地方.
但是,为什么要这么做呢?为什么要让一个按钮扮演观察者和被观察者两个不同的角色呢? 因为, 我们最终关心的是谁被注册了什么事件, 以及事件被触发时做了什么动作, 而不关心监听和触发的对象是不是不同的, 所以, 在观察者和被观察者的设计上我们有了更灵活的空间, 我们可以设计将观察者和被观察者设计成不同的对象,也可以设计成一个对象, 很明显, 在这里我们没有必要将他们设计成两个不同的对象