一、观察者模式简介(Brief Introduction)
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象在状态发生变化的时,会通知所有观察者对象,使他们能够自动更新自己。
二、解决的问题(What To Solve)
当一个对象的改变需要同时改变其他对象的时候,而且不知道有多少对象有待改变时,应该考虑使用观察者模式。
观察者模式所做的工作其实就是解除耦合,让耦合的双方都依赖于抽象,而不是依赖于具体,从而使的各自的变化都不会影响另一边的变化。
三、观察者模式分析(Analysis)
Subject类:它把所有对观察者对象的引用保存在一个聚集里面,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
public void Notify()
{
for(Observer o:observers)
{
o.Update();
}
ConcreteSubject类: 具体的主题,将有关状态存入具体观察者对象,在具体主题的内部状态改变时,给所有登记国的观察者发出通知。
Observer接口:抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己
ConcreteObserver:具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调
package observer;
import java.util.ArrayList;
import java.util.List;
/**
*************************************
* @Title Subject.java
* @Author 张作强
* @Date 2010-8-22
* @Comment Subject类,主题或者抽象通知者
*************************************
*/
public abstract class Subject{
private List<Observer> observers = new ArrayList<Observer>();
// 添加一个观察者
public void Attach(Observer observer){
this.observers.add(observer);
}
// 移除一个观察者
public void Detach(Observer observer){
this.observers.remove(observer);
}
// 通知每一个观察者
public void Notify(){
for(Observer o : this.observers){
o.Update();
}
}
}
package observer;
/**
*************************************
* @Title ConcreteSubject.java
* @Author 张作强
* @Date 2010-8-22
* @Comment ConcreteSubject类,具体主题或者具体通知者
*************************************
*/
public class ConcreteSubject extends Subject {
private String subjectState;
public String getSubjectState() {
return this.subjectState;
}
public void setSubjectState(String subjectState) {
this.subjectState = subjectState;
}
}
package observer;
public interface Observer {
public void Update();
}
package observer;
public class ConcreteObserver implements Observer {
private String name;
private String observerState;
private ConcreteSubject subject;
public String getObserverState() {
return observerState;
}
public void setObserverState(String observerState) {
this.observerState = observerState;
}
public ConcreteObserver(ConcreteSubject subject,String name){
this.subject = subject;
this.name = name;
}
public void Update() {
observerState = subject.getSubjectState();
System.out.println("观察者 " + name +" 的新状态是 " + observerState);
}
}
package observer;
public class Test {
public static void main(String[] args) {
ConcreteSubject cs = new ConcreteSubject();
Observer observer1 = new ConcreteObserver(cs, "张作强");
Observer observer2 = new ConcreteObserver(cs, "陈惠仪");
cs.Attach(observer1);
cs.Attach(observer2);
cs.setSubjectState("OK");
cs.Notify();
}
}
结果:
观察者 张作强 的新状态是 OK
观察者 陈惠仪 的新状态是 OK
观察者模式的优点:
1.在被观察者和观察者之间建立一个抽象的松耦合;
2.支持广播通信。被观察者会向所有登记过的观察者发出通知。
观察者模式也有如下缺点:
1.如果一个被观察者对象有很多直接或间接的观察者的话,将所有的观察者都通知到会花费很多时间;
2.如果在被观察者之间有循环依赖的话,被观察者会触发它们进行循环调用,导致系统崩溃,在使用此模式时应特别注意这一点;
3.如果对观察者的通知是通过另外的线程进行异步投递的话,系统必须保证投递是以自恰的方式进行的;
4.虽然观察者模式可以使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制让观察者知道所观察的对象是怎么发生变化的。