设计模式——观察者(初步)

来源:互联网 发布:sweetalert.js下载 编辑:程序博客网 时间:2024/06/17 06:57

   本章继续设计模式中的观察者模式的学习。本章将以问答的形式给出。

1. 什么是观察者模式?

    观察者模式定义了对象之间一对多的关系,当一个对象发生变化时,所有其他对象都会收到该对象变化的消息。

2.能举个典型的例子吗?

    我们都对马云的围脖感兴趣,然后我们都加他为好友。每次他更新围脖,我们都会收到他新的消息。其实可以把马云看作一个主题,我们都是订阅了主题的观察者,每当主题变化,我们都能收到最新的消息。这就是观察者模式。

3.那代码怎么写?

   我先贴一段,大家看效果,然后再说内部如何实现.

import java.util.Observer;/** * 这里是围脖    * 用户小明关注了JackMsgSubject的变化 */public class Weibo {public static void main(String[] args) {//马云的围脖JackMsgSubject jackMsg = new JackMsgSubject();//小明关注了马云Observer xiaoming  = new XiaoMing(jackMsg);//马云发了一条新的消息jackMsg.putNewMsg("阿里巴巴是个快乐的青年!");//然后}}
主题部分代码,主题是数据的承载者,当主题变化时,所有订阅者都会收到消息:

import java.util.Observable;/** * 主题,变化的对象,包含变化的数据 * Observable是一类 ,而不是接口!!! * JackMsgSubject 是继承自Observable 而不是implements    */public class JackMsgSubject extends  Observable {private String aMsg;public void putNewMsg(String newMsg){//发了一个新围脖this.aMsg = newMsg;//aMsg已经发生变化this.setChanged();//通知所有关注我人this.notifyObservers();}public String getNewMsg(){return aMsg;}}
看下小明,他关注了主题JackMsg,当JackMsg发生变化时,小明会收到JackMsg变化的消息内容。观察者的实现:

import java.util.Observable;import java.util.Observer;/** * 小明 是一个观察者  * 他关注了jack 的围脖JackMsgSubject变化  */public class XiaoMing implements Observer {    //我关注了某人  private  Observable abs;public XiaoMing(Observable abs){//小明关注了absthis.abs=abs;//将自己加入abs队列中 以监听其变化    this.abs.addObserver(this);}public void update(Observable o, Object arg) {if(o instanceof JackMsgSubject){JackMsgSubject jackMsg = (JackMsgSubject) o;System.out.print("我收到了Jack的消息:"+jackMsg.getNewMsg());}}}
当执行main()函数的时候,我们就会在console打印出:



4.观察者如何实现的?

我们这里用的是jdk自带的Observable类/observer接口。其中Observable为主题,包含变化的数据,很诡异的Observable竟然是一个类,而不是接口!!我们看看Observable里面干了什么:

public class Observable {    private boolean changed = false;    private Vector obs;  //此处存储的是所有观察者名单 相当于注册列表     //****省略其他方法 public void notifyObservers(Object arg) {        /*         * a temporary array buffer, used as a snapshot of the state of         * current Observers.         */        Object[] arrLocal;        synchronized (this) {                  if (!changed)    //判断是否发生变化                return;            arrLocal = obs.toArray(); // 将所有观察者拿出来            clearChanged();        }        for (int i = arrLocal.length-1; i>=0; i--)   // 每个发送数据变化的消息 前提是这些观察者之间没有先后的逻辑顺序            ((Observer)arrLocal[i]).update(this, arg);  //调用所有观察者Observer共同实现的接口 update()    }

大家看代码就可以发现,对于主题来说,维护了一个观察者的Vector,当有新的观察者想要关注该主题是,只需要将其加入Vector,即调用vector.add()方法。当变化发生的时候,取出Vecotor中每个观察者,逐一条用Observer接口中的update方法即可。

5. 观察者中的推/拉模式

       我个人理解,新浪围脖是个大的观察者网络。每个人既可以是主题,也可以是观察者。开始的时候,消息是推送的,什么意思呢?就是有100个人关注了我,那么我发一条新围脖,这条信息会推送到100个人的页面上,不管这个用户是否在线,也不管后面的消息是否会被更新的覆盖,反正就是推过去了。这样看起来好简单,但是问题也是很明显的。就是消息发过去了,用户也未必会关注,或者至少不会立刻关注,这就造成了网络资源的浪费,而且使得在线用户收到消息速度变慢。

      那可以部分采用“拉”的模式,在线用户我推送,不在线用户,等下次上线再去把这个消息“拉”回来,既保证在线用户收消息速度,又保证所有人都可以收到这条消息不丢失。

      如何实现“拉”的方式?其实我们这里就是“拉”模式。因为主题JackMsgSuject中实现了 getNewMsg()方法,这样观察者在收到新消息通知时,可以选择自己去拉出来,或者延迟去取。


好了,初步的观察者模式就到这里了。对于业务逻辑比较复杂的观察者模式,最好是自己实现一套机制,因为JDK中主题Obserable是个类!而不是接口!所以涉及到继承等操作的时候,灵活性会大大降低!



      






 


原创粉丝点击