2.观察者模式
观察者模式很好理解,类似于邮件订阅和RSS订阅,当我们浏览一些博客或wiki时,经常会看到RSS图标,就这的意思是,当你订阅了该文章,如果后续有更新,会及时通知你。其实,简单来讲就一句话:当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化!对象之间是一种一对多的关系。
一.要点
- 观察者模式定义了对象之间的一对多的关系,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
- 主题(被观察者)通过一个共同的接口来更新观察者。
- 有多个观察者时,不可以依赖特定的通知次序。
- 观察者模式提供了一种对象设计,让主题和观察者之间松耦合。改变主题或者观察者其中一方,并不会影响另一方。
- 使用此模式时,可以从被观察者处推(push)或拉(pull)数据。
- Java有多种观察者模式的实现,包括了通用的java.util.Observable。
- 如果有必要的话,可以实现自己的Observable。
- 在JavaBeans和Swing中,也都实现了观察者模式。
二.设计原则
1.当两个对象之间松耦合,他们依然可以交互,但是不太清楚彼此的细节。松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的互相依赖降到了最低。
当有新的具体类需要作为观察者时,要做的就是在新的类里实现此观察者接口,然后注册为观察者即可。
2.找出程序中会变化的方面,然后将其和固定不变的方面相分离。
在观察者模式中,会改变的是主体的状态,以及观察者的数目和类型。用这个模式,你可以改变依赖于主题状态的的对象,却不必改变主题。这就叫提前规则!
3.针对接口编程,不针对实现编程。
主题和观察者都是用接口,观察者利用主题的接口向主题注册,而主题利用观察者的而接口通知观察者。这样可以让两者之间运作正常,又同时具有松耦合的优点。
4.多用组合,少用继承。
观察者模式利用“组合”将许多观察者组合进主题中,对象之间的这种关系不是通过继承产生的,而是在运行时利用组合方式而产生的。
三.UML关系图
图中,MySubject类就是我们的主对象,Observer1和Observer2是依赖于MySubject的对象,当MySubject变化时,Observer1和Observer2必然变化。AbstractSubject类中定义着需要监控的对象列表,可以对其进行修改:增加或删除被监控对象,且当MySubject变化时,负责通知在列表内存在的对象。
四.Java内置的观察者模式
主题(被观察者):扩展自java.util.Observable类。(因为是类,所以存在一定的局限性)。
观察者:实现java.util.Observer接口。
通过调用Observable对象的addObserver()和deleteObserver()方法添加或者删除观察者。
被观察者送出通知时,需要两个步骤:
1.调用setChanged()方法,标记状态已经改变的事实;
2.调用两种notifyObservers()方法中的一个:
notifyObservers()或notifyObservers(Object arg):当通知时,后者的版本可以传送任何的数据对象给每一个观察者。
观察者接收通知:
update(Observable o, Object arg)
主题本身是第一个参数,第二个参数为notifyObservers(Object arg)的数据对象,如果没有则为空。
Java内置的Observer模式支持push和pull两种数据传递方式:
push:由被观察者把数据推给观察者。
pull:观察者从被观察者中拉数据。
五.实现代码
一个Observer接口:
public interface Observer { public void update(); }
一个实现类:
public class Observer1 implements Observer { @Override public void update() { System.out.println("observer1 has received!"); } }
Subject接口:
public interface Subject { /*增加观察者*/ public void add(Observer observer); /*删除观察者*/ public void del(Observer observer); /*通知所有的观察者*/ public void notifyObservers(); /*自身的操作*/ public void operation(); }
Subject实现类:
public abstract class AbstractSubject implements Subject { private Vector<Observer> vector = new Vector<Observer>(); @Override public void add(Observer observer) { vector.add(observer); } @Override public void del(Observer observer) { vector.remove(observer); } @Override public void notifyObservers() { Enumeration<Observer> enumo = vector.elements(); while(enumo.hasMoreElements()){ enumo.nextElement().update(); } } } public class MySubject extends AbstractSubject { @Override public void operation() { System.out.println("update self!"); notifyObservers(); } }
测试类:
public class ObserverTest { public static void main(String[] args) { Subject sub = new MySubject(); sub.add(new Observer1()); sub.operation(); } }
输出:
update self!
observer1 has received!
参考:
《Head Frist 设计模式》
http://blog.csdn.net/zhangerqing/article/details/8243942
http://www.cnblogs.com/mengdd/archive/2013/01/03/2843298.html