有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
将一个系统分割成一个一些类相互协作的类有一个不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。观察者就是解决这类的耦合关系的。
3.1 抽象主题(Subject):它把所有观察者对象的引用保存到一个聚集【使用集合】里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
3.2 具体主题(ConcreteSubject):将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
3.3 抽象观察者(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
3.4 具体观察者(ConcreteObserver):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。
ConcreteSubject泛化了Subject接口,Subject接口持有Observer接口的引用【PS:隐含了1对多关系,一个Subject对应多个Observer,但是对应哪个具体的Observer是不知道的】
ConcreteObserver泛化了Observer接口,并持有Subject接口的引用用于初始化
1.Subject.java
public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObservers(); }2.Observer.java
public interface Observer { public void update(float temp,float humidity,float pressure); }
public class WeatherData implements Subject { private ArrayList<Observer> observers; private float humidity; private float pressure; private float temp; public WeatherData() { observers=new ArrayList(); } public float getHumidity() { return humidity; } public float getPressure() { return pressure; } public float getTemperature() { return temp; } @Override public void notifyObservers() { // TODO Auto-generated method stub for(int i=0;i<observers.size();i++) { Observer observer=observers.get(i); observer.update(temp, humidity, pressure); } } @Override public void registerObserver(Observer o) { // TODO Auto-generated method stub observers.add(o); } @Override public void removeObserver(Observer o) { // TODO Auto-generated method stub int i=observers.indexOf(o); observers.remove(i); } public void measurementsChanged() { notifyObservers(); } public void SetMeasurements(float temp,float humidity,float pressure) { this.temp=temp; this.humidity=humidity; this.pressure=pressure; measurementsChanged(); } }
4.DisPlayElement.java【简单封装的一个接口】
public interface DisPlayElement { public void display(); }
public class CurrentConditionsDisplay implements Observer, DisPlayElement { private float humidity; private float pressure; private float temp; private Subject weatherData; public CurrentConditionsDisplay(Subject weatherData) { this.weatherData=weatherData; weatherData.registerObserver(this); } @Override public void update(float temp, float humidity, float pressure) { // TODO Auto-generated method stub this.temp=temp; this.humidity=humidity; this.pressure=pressure; display(); } @Override public void display() { // TODO Auto-generated method stub System.out.println("温度: "+temp+" 湿度: "+humidity+" 气压: "+pressure); } }
6.Test.java
public class Test { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub WeatherData weatherdata=new WeatherData(); CurrentConditionsDisplay currentDisplay=new CurrentConditionsDisplay(weatherdata); weatherdata.SetMeasurements(90, 90, 91); weatherdata.SetMeasurements(91, 91, 90); weatherdata.SetMeasurements(92, 92, 91); } }
关联和依赖的区别:
依赖关系(Dependency):是类与类之间的连接,依赖总是单向的。依赖关系代表一个类依赖于另一个类的定义。下面的例子中class A 依赖与class B、C、D。
An observable object can have one or more observers. An observer may be any object that implements interface
Observer. After an observable instance changes, an application calling the
Observable
‘s notifyObservers
method causes all of its observers to be notified of the change by a call to their
update
method.
1.Observer.java
public interface Observer { /** * This method is called whenever the observed object is changed. An * application calls an <tt>Observable</tt> object‘s * <code>notifyObservers</code> method to have all the object‘s * observers notified of the change. * * @param o the observable object. * @param arg an argument passed to the <code>notifyObservers</code> * method. */ void update(Observable o, Object arg); }2.Observable.java
public class Observable {
private boolean changed = false;
private Vector obs;
public Observable() {
obs = new Vector();
}
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
public void notifyObservers() {
notifyObservers(null);
}
public void notifyObservers(Object arg) {
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);
}
public synchronized void deleteObservers() {
obs.removeAllElements();
}
protected synchronized void setChanged() {
changed = true;
}
protected synchronized void clearChanged() {
changed = false;
}
public synchronized boolean hasChanged() {
return changed;
}
public synchronized int countObservers() {
return obs.size();
}
}
5.1 优点
5.1.1 观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。
5.2 缺点
5.2.1 依赖关系并未完全解除,抽象通知者依旧依赖抽象的观察者。
5.3 适用场景
5.3.1 当一个对象的改变需要给变其它对象时,而且它不知道具体有多少个对象有待改变时。
5.3.2 一个抽象某型有两个方面,当其中一个方面依赖于另一个方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。
原文:http://blog.csdn.net/mariofei/article/details/23021705