观察者模式——————个人理解

来源:互联网 发布:淘宝客服服务回复 编辑:程序博客网 时间:2024/05/20 05:47
1、观察者模式会分别定义一个主题接口Sunject和观察者接口Observer。
2、主题接口:一般有add()添加观察者、del()删除观察者、notify()通知观察者。
为什么要有add( )、del( )方法呢?因为有新的观察者添加进来,你要在主题接口里新建
一个List<Object> 把他们存起来,需要通知观察者,就遍历list来通知所有。删除就是有人
不想观察了就从list中remove掉。
3、观察者接口:有一个updata()方法。
4、主体实现类:在其方法中对观察者的调用都是依赖Observer接口,利用多态实现
对观察者实现类的操作。利用对象数组方式对众多观察者对象进行存储。
5、观察者实现类:可以有多个,分别实现Observer接口。观察者可以在构造函数中调用主题
中的add方法,也可以在Test中调用。当被通知更新时就是被调用updata()方法。
不同观察者在实现接口中的updata方法时,可以有不同的实现。


代码如下:
<span style="font-size:18px;">//主题接口public interface Subject {void add(Observer o);void del(Observer o);void call();//实现主题public class WeatherData implements Subject {private List<Object> list;private float w;private float s;private float p;public WeatherData() {list = new ArrayList<Object>();}@Overridepublic void add(Observer o) {list.add(o);}@Overridepublic void del(Observer o) {int i=list.indexOf(o);if(i>=0){list.remove(i);}}@Overridepublic void call() {for(int i=0;i<list.size();i++){Observer obs=(Observer)list.get(i);obs.updata(w, s, p);}}public void setTemp(float w,float s,float p){this.w=w;this.s=s;this.p=p;call();}}}//观察者接口public interface Observer {void updata(float w,float s,float p);}//观察者接口的具体实现public class CurrentDisplay implements Observer {private float w;private float s;private Subject wd;public CurrentDisplay(Subject wd) {this.wd=wd;wd.add(this);}@Overridepublic void updata(float w, float s, float p) {this.w=w;this.s=s;display();}public void display(){System.out.println("w= "+w+"s= "+s);}}public class Test {public static void main(String[] args) {WeatherData s=new WeatherData();Observer o=new CurrentDisplay(s);s.setTemp(30.0f, 0.8f, 100.0f);}}</span>


小结:观察者模式是一种一对多关系,主题只有一个,而观察者众多。主题与观察者之间的
      依赖都是通过父类接口实现,这样可以达到松耦合的目的。


观察者模式的效果有以下的优点:
第一、观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体
      观察者列表,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具
      体观察者,它只知道它们都有一个共同的接口。由于被观察者和观察者没有紧密地耦合在一起,
      因此它们可以属于不同的抽象化层次。如果被观察者和观察者都被扔到一起,
      那么这个对象必然跨越抽象化和具体化层次。
第二、观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知,

观察者模式有下面的缺点:
第一、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
第二、如果在被观察者之间有循环依赖的话,被观察者会触发它们之间进行循环调用,导致系统崩溃。
      在使用观察者模式是要特别注意这一点。
第三、如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的。
第四、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制
      使观察者知道所观察的对象是怎么发生变化的。



在要说的分歧在这里:

“推”push 的方式是指,Subject维护一份观察者的列表,每当有更新发生,Subject会把更新消息主动推送到各个Observer去。

“拉”pull 的方式是指,各个Observer维护各自所关心的Subject列表,自行决定在合适的时间去Subject获取相应的更新数据。


“推”的好处包括:
1、高效。如果没有更新发生,不会有任何更新消息推送的动作,即每次消息推送都发生在确确实实的更新事件之后,都是有意义的。

2、实时。事件发生后的第一时间即可触发通知操作。

3、可以由Subject确立通知的时间,可以避开一些繁忙时间。

4、可以表达出不同事件发生的先后顺序。


“拉”的好处包括:

1、如果观察者众多,Subject来维护订阅者的列表,可能困难,或者臃肿,把订阅关系解脱到Observer去完成。

2、Observer可以不理会它不关心的变更事件,只需要去获取自己感兴趣的事件即可。

3、Observer可以自行决定获取更新事件的时间。

4、拉的形式可以让Subject更好地控制各个Observer每次查询更新的访问权限。
0 0
原创粉丝点击