观察者模式(Observer Pattern)也称发布订阅模式,它的目的是定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
观察者模式的类图如下图所:
观察者模式具有以下4个角色:
角色 | 说明 |
---|---|
抽象主题(Subject)角色 | 该角色又称为“被观察者”,可以增加和删除观察者对象。 |
抽象观察者(Observer)角色 | 该角色为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。 |
具体主题(Concrete Subject)角色 | 该角色又称为“具体被观察者”,它将有关状态存入具体观察者对象,在具体主题的内部状态改变时,给所有登记过的观察者发出通知。 |
具体观察者(Concrete Observer)角色 | 该角色实现抽象观察者所要求的更新接口,以便使自身的状态与主题的状态相协调。 |
定义抽象主题(Subject)角色类
package com.shixun.design.observer;
/**
* 抽象主题:被观察者
*/
interface Subject {
// 登记一个新的观察者
public void attach(Observer obs);
// 删除一个登记过的观察者
public void detach(Observer obs);
// 通知所有登记过的观察者对象
public void notifyObserver();
}
定义抽象观察者(Observer)角色类
package com.shixun.design.observer;
/**
* 抽象观察者:为所有的具体观察者定义一个接口
*/
interface Observer {
// 更新方法
public void update();
}
定义具体主题(Concrete Subject)角色类
package com.shixun.design.observer;
import java.util.Enumeration;
import java.util.Vector;
/**
* 具体主题:具体被观察者
*/
class ConcreteSubject implements Subject {
private Vector obsVector = new Vector();
// 登记一个新的观察者
public void attach(Observer obs) {
obsVector.add(obs);
}
// 删除一个登记过的观察者
public void detach(Observer obs) {
obsVector.remove(obs);
}
// 通知所有登记过的观察者对象
public void notifyObserver() {
for (Observer e : obsVector) {
e.update();
}
}
// 返回观察者集合的Enumeration对象
public Enumeration observers() {
return obsVector.elements();
}
// 业务方法,改变状态
public void change() {
this.notifyObserver();
}
}
定义具体观察者(Concrete Observer)角色类
package com.shixun.design.observer;
/**
* 具体观察者:实现抽象观察者所要求的更新接口
*/
class ConcreteObserver implements Observer {
// 实现更新方法
public void update() {
System.out.println(this+"收到通知,并进行处理!");
}
}
定义测试类:
package com.shixun.design.observer;
import com.shixun.design.strategy.ConcreteStrategy;
import com.shixun.design.strategy.Context;
public class Test {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
ConcreteObserver observer = new ConcreteObserver();
ConcreteObserver observer1 = new ConcreteObserver();
ConcreteObserver observer2 = new ConcreteObserver();
subject.attach(observer);
subject.attach(observer1);
subject.attach(observer2);
subject.change();
}
}
运行结果如下:
观察者模式具有以下几个优点:
观察者和被观察者之间是抽象耦合。被观察者角色所知道的只是一个具体观察者集合,每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体的观察者,它只知道它们都有一个共同的接口。由于被观察者和观察者没有紧密的耦合在一起,因此它们可以属于不同的抽象化层次,且都非常容易扩展。
支持广播通信。被观察者会向所有登记过的观察者发出通知,这就是一个触发机制,形成一个触发链。
观察模式的缺点如下:
观察者模式的应用场景如下: