/**
* @Title : 被观察者接口
* @author qiucd
* @date 2016-1-21
*/
public interface Observable {
/**
* 增加一个观察者
* @param observer
*/
public void addObserver(Observer observer);
/**
* 删除一个观察者
* @param observer
*/
public void deleteObserver(Observer observer);
/**
* 既然要观察,我发生改变了他也应该有所动作,通知观察者
* @param context
*/
public void notifyObservers(String context);
}
/**
* @Title : 观察者接口
* @author qiucd
* @date 2016-1-21
*/
public interface Observer {
//一发现别人有动静,自己也要行动起来
public void update(String context);
}
/**
* @Title : 被观察者接口
* @author qiucd
* @date 2016-1-21
*/
public interface IHanFeiZi {
/**
* 韩非子也是人,也要吃早饭的
*/
public void haveBreakfast();
/**
* 韩非子也是人,是人就要娱乐活动
*/
public void haveFun();
}
/**
* @Title : 被观察者实现类
* @author qiucd
* @date 2016-1-21
*/
public class HanFeiZi implements Observable,IHanFeiZi {
//定义个变长数组,存放所有的观察者
private ArrayList<Observer> observerList = new ArrayList<Observer>();
//增加观察者
public void addObserver(Observer observer) {
this.observerList.add(observer);
}
//删除观察者
public void deleteObserver(Observer observer) {
this.observerList.remove(observer);
}
//通知所有的观察者
public void notifyObservers(String context) {
for(Observer obs : observerList){
obs.update(context);
}
}
@Override
public void haveBreakfast() {
System.out.println("韩非子:开始吃饭了...");
this.notifyObservers("韩非子在吃饭");
}
@Override
public void haveFun() {
System.out.println("韩非子:开始娱乐了...");
this.notifyObservers("韩非子在娱乐");
}
}
public class LiSi implements Observer {
//首先李斯是个观察者,一旦韩非子有活动,他就知道,他要开始向老板汇报
public void update(String context) {
System.out.println("李斯:观察到韩非子活动,开始向老板汇报...");
this.reportToQinShiHuang(context);
System.out.println("李斯:汇报完毕!");
}
private void reportToQinShiHuang(String reprotContext){
System.out.println("李斯:报告,秦老板! 韩非子有活动了-----> "+reprotContext);
}
}
public class LiuSi implements Observer {
//刘斯,观察到韩非子活动后,自己也得做一些事
public void update(String context) {
System.out.println("刘斯:观察者到韩非子活动,自己也开始活动了...");
this.happy(context);
System.out.println("刘斯:乐死了...\n");
}
private void happy(String context){
System.out.println("刘斯:因为"+context+",--所以我快乐呀!");
}
}
public class WangSi implements Observer {
//王斯,看到韩非子有活动
public void update(String context) {
System.out.println("王斯:观察者到韩非子活动,自己也开始活动了...");
this.cry(context);
System.out.println("王斯:哭死了...\n");
}
private void cry(String str){
System.out.println("王斯:因为"+str+",--所以我悲伤呀!");
}
}
/**
* @Title : 观察者模式
* @author qiucd
* @date 2016-1-21
*/
public class Client {
public static void main(String[] args) {
//三个观察者产生出来
Observer liSi = new LiSi();
Observer wangSi = new WangSi();
Observer liuSi = new LiuSi();
//定义韩非子
HanFeiZi hanFeiZi = new HanFeiZi();
//我们后人根据历史,描述这个场景,有三个人在观察韩非子
hanFeiZi.addObserver(liSi);
hanFeiZi.addObserver(wangSi);
hanFeiZi.addObserver(liuSi);
//然后这里我们看看韩非子在干什么;
hanFeiZi.haveBreakfast();
}
}
运行结果:
韩非子:开始吃饭了...
李斯:观察到韩非子活动,开始向老板汇报...
李斯:报告,秦老板! 韩非子有活动了-----> 韩非子在吃饭
李斯:汇报完毕!
王斯:观察者到韩非子活动,自己也开始活动了...
王斯:因为韩非子在吃饭,--所以我悲伤呀!
王斯:哭死了...
刘斯:观察者到韩非子活动,自己也开始活动了...
刘斯:因为韩非子在吃饭,--所以我快乐呀!
刘斯:乐死了...
观察者模式的注意事项:
广播链问题:
如果你做过数据库的触发器,你就应该知道有一个触发器链的问题,比如 表A上写了一个触发器,内容是一个字段更新后更新表B的一条数据,而表B上也有个触发器,要更新表C,表C也有触发器… 完蛋了,这个数据库基本上毁掉了!我们的观察者模式也是一样的问题,一个观察者可以有双重身份,既是观察者,也是被观察者,这没什么问题呀,但是链一旦建立,这个逻辑就比较复杂,可维护非常差,所以建议,在一个观察者模式中最多出现一个对象既是观察者也是被观察者,也就是说消息最多转发一次(传递两次),这还是比较好控制的。
它和责任链模式的最大区别就是观察者广播链的过程中消息是随时更改的,它是由相邻的两个节点协商的消息结构;而责任链模式在消息传递过程中基本上保持消息不可变,如果要改变,也只是在原有的消息上进行修正。
异步处理问题:
EJB是一个非常好的例子,被观察者发生动作了,观察者要做出回应,如果观察者比较多,而且处理时间比较长怎么办?那就用异步呗,异步处理就要考虑线程安全和队列安全的问题,这个大家有时间看看Message Queue,就会有更深的了解。
订阅发布模型:
观察者也叫发布/订阅模型(Publish/Subscribe),如果你做过EJB的开发,这个你绝对不陌生,EJB是个折腾死人不偿命的玩意,写个Bean要实现,还要继承,再加上一堆的配置文件,小项目凑合,要知道EJB开发的基本上都不是小项目,到最后是每个项目成员都在骂EJB这个忽悠人的东西;但EBJ3是个非常优秀的框架,还是算比较轻量级,写个Bean只要加个Annotaion就成了,配置文件减少了。而且引入了依赖注入的概念。虽然只是EJB2的翻版,但是毕竟还是前进了一步。在EJB中有3个类型的Bean:Session Bean,Entity Bean和MessageDriven Bean, 说下MessageDriven Bean(一般简称MDB),消息驱动Bean,消息的发布者(Provider) 发布一个消息,也就是一个消息驱动Bean,通过EJB容器(一般是Message Queue消息队列) 通知订阅者做出回应,从原理上看很简单,就是观察者模式的升级版,或者说是观察者模式的BOSS版。