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

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

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){
		//小明关注了abs
		this.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是个类!而不是接口!所以涉及到继承等操作的时候,灵活性会大大降低!



      






 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值