观察者模式,顾名思义,就是有人在做,有人在看。所以,观察者模式涉及到两个群体,观察者和被观察者,比如说订阅新闻,某网站提供新闻拱客户阅读,只要客户订阅了该网站新闻,每当网站提供新的新闻素材时,就会通知客户,客户收到相应通知后更新新闻列表,如果客户取消订阅,那么网站有更新时,客户就不会收到新闻,这里网站就是被观察者,客户就是观察者,他们以及他们之间的订阅关系构成了观察者模式的一个例子。
定义:观察者模式定义了对象之间的一对多的依赖关系,当一个对象更新时,所以的依赖于该对象的对象都会收到通知并自动更新。
从定义可以看出,被观察者是一对多关系的一那一端。
UML图:
从图中我们可以看到,主题只依赖观察者接口,这里又一次遵循了松耦合原则,只要具体的观察这类实现观察者接口,那么主题和观察者直接就能交互,无论具体观察者实现类如何变化,记住,解耦是设计模式中最最基本的原则之一。
例子:
package subject;
import observer.MyObserver;
/**
* 主题
*
* @author 梅东
*
*/
public interface Subject {
/**
* 注册观察者
*
* @param observer
*/
void registerObserver(MyObserver observer);
/**
* 移除观察者
*
* @param observer
*/
void removeObserver(MyObserver observer);
/**
* 通知观察者更新信息
*/
void notifyObservers();
}
package observer;
/**
* 观察者
*
* @author 梅东
*
*/
public interface MyObserver {
/**
* 接收主题消息后执行更新操作
*/
void update();
}
package subject;
import java.util.ArrayList;
import java.util.List;
import observer.MyObserver;
public class ConcreteSubject implements Subject {
private List<MyObserver> observers = new ArrayList<MyObserver>();
@Override
public void registerObserver(MyObserver observer) {
observers.add(observer);
}
@Override
public void removeObserver(MyObserver observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (MyObserver observer : observers) {
observer.update();
}
}
public void stateChanged() {
notifyObservers();
}
}
package observer;
import subject.Subject;
public class MyObserverImpl_A implements MyObserver {
private Subject subject;
/**
* 在构造函数中注册主题
*
* @param subject
*/
public MyObserverImpl_A(Subject subject) {
this.subject = subject;
this.subject.registerObserver(this);
}
@Override
public void update() {
System.out.println("A 接收到了新的订阅消息");
}
}
package observer;
import subject.Subject;
public class MyObserverImpl_B implements MyObserver {
private Subject subject;
/**
* 在构造函数中注册主题
*
* @param subject
*/
public MyObserverImpl_B(Subject subject) {
this.subject = subject;
this.subject.registerObserver(this);
}
@Override
public void update() {
System.out.println("B 接收到了新的订阅消息");
}
}
package test;
import observer.MyObserver;
import observer.MyObserverImpl_A;
import observer.MyObserverImpl_B;
import subject.ConcreteSubject;
public class TestDriver {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
MyObserver observerA = new MyObserverImpl_A(subject);
MyObserver observerB = new MyObserverImpl_B(subject);
subject.stateChanged();
System.out.println("observerB对象取消订阅主题=================>");
subject.removeObserver(observerB);
subject.stateChanged();
}
}
运行结果:
A 接收到了新的订阅消息
B 接收到了新的订阅消息
observerB对象取消订阅主题=================>
A 接收到了新的订阅消息
在具体的主题实现中,使用了ArrayList来存储注册的观察者对象,在观察者构造函数中,直接订阅主题。测试结果表明,每次主题状态发生改变后,观察者都会收到通知,并执行相应操作,在移除观察者observerB后,主题发生改变后,observerB并没有收到通知,只有注册的observerA才收到通知。
观察这模式也很简单,但是应用很广泛,最常见的就是图形编程中的事件机制,有兴趣的朋友可以深入研究。