所谓“观察”,是为观而察之。就像医院的重症病房,医生不能时时刻刻看着病人,就需要护士或者家属全程看护,一有情况就通知医生。其中,病人是被观察者、护士或家属是观察者。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一主题对象。这个主题对象在状态发生改变时,会通知所有观察者对象,使它们能更新自己。
类图如下
图中的各个角色有
抽象主题(Subject):它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
具体主题(ConcreteSubject):将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
抽象观察者(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
具体观察者(ConcreteObserver):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。
做了一个简单的例子:
首先是Subject(被观察者的抽象接口)和ConcreteSubject(被观察者的具体实现)
public interface Watched {
public void addWatcher(Watcher watcher);
public void removeWatcher(Watcher watcher);
public void notifyWatchers(String str);
}
import java.util.ArrayList;
import java.util.List;
public class ConcreteWatched implements Watched
{
// 存放观察者
private List<Watcher> list = new ArrayList<Watcher>();
@Override
public void addWatcher(Watcher watcher)
{
list.add(watcher);
}
@Override
public void removeWatcher(Watcher watcher)
{
list.remove(watcher);
}
@Override
public void notifyWatchers(String str)
{
// 自动调用实际上是主题进行调用的
for (Watcher watcher : list)
{
watcher.update(str);
}
}
}
其次是Observer(观察者的抽象接口)和ConcreteObserver(具体观察者类)
public interface Watcher {
public void update(String str);
}
public class ConcreteWatcher1 implements Watcher
{
@Override
public void update(String str)
{
System.out.println(str+",观察者1做出响应。");
}
}
public class ConcreteWatcher2 implements Watcher
{
@Override
public void update(String str)
{
System.out.println(str+",观察者2做出响应。");
}
}
public class ConcreteWatcher3 implements Watcher
{
@Override
public void update(String str)
{
System.out.println(str+",观察者3做出响应。");
}
}
最后是客户端了
public class POC {
public static void main(String[] args)
{
Watched subject = new ConcreteWatched();
Watcher watcher1 = new ConcreteWatcher1();
Watcher watcher2 = new ConcreteWatcher2();
Watcher watcher3 = new ConcreteWatcher3();
subject.addWatcher(watcher1);
subject.addWatcher(watcher2);
subject.addWatcher(watcher3);
subject.notifyWatchers("状态发生改变");
}
}
总结得出
优点:观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。
缺点: 依赖关系并未完全解除,抽象通知者依旧依赖抽象的观察者。
使用场景:1.当一个对象的改变需要给变其它对象时,而且它不知道具体有多少个对象有待改变时。2.一个抽象某型有两个方面,当其中一个方面依赖于另一个方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。