一、定义
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
二、通用类图
1:Subject 被观察者
定义被观察者必须实现的职责,它必须能够动态增加、取消观察者。被观察者必须实现的职责:管理观察者并通知观察者。
2:Observer 观察者
观察者接收到消息后,即进行update操作,对接收到的消息进行处理。
3:ConcreteSubject 具体的被观察者
定义被观察者自己的业务逻辑,同时定义对哪些事件进行通知。
4:ConcreteObserver 具体的观察者
每个观察者在接收到信息后的处理反应是不同的,各个观察者有自己的处理逻辑。
三、通用代码
1:被观察者
import java.util.Vector;
public abstract class Subject {
//定义一个观察者数组
private Vector<Observer> obsVector = new Vector<Observer>();
//增加一个观察者
public void addObserver(Observer observer) {
this.obsVector.add(observer);
}
//删除一个观察者
public void deleteObserver(Observer observer) {
this.obsVector.remove(observer);
}
//通知所有观察者
public void notifyObservers() {
for(Observer o : this.obsVector) {
o.update();
}
}
}
public class ConcreteSubject extends Subject {
//具体的业务
public void doSomething() {
super.notifyObservers();
}
}
public interface Observer {
void update();
}
4:具体观察者
public class ConcreteObserver implements Observer {
@Override
public void update() {
System.out.println("接收到信息,并进行处理");
}
}
5:场景类
public class Client {
public static void main(String[] args) {
//创建一个被观察者
ConcreteSubject subject = new ConcreteSubject();
//定义一个观察者
Observer observer = new ConcreteObserver();
//观察者观察被观察者
subject.addObserver(observer);
//观察者开始活动
subject.doSomething();
}
}
四、优缺点
1:观察者和被观察者之间是抽象耦合。不管是增加观察者还是被观察者都很容易,。
2:建立一套触发机制。
3:观察者模式需要考虑开发效率和运行效率问题,一个被观察者、多个观察者,开发和调试就会比较复杂,而且在Java中消息的通知默认是顺序执行,一个观察者卡壳,会影响整体的执行效率。
五、注意点
1:广播链问题。
一个观察者可以有两重身份,既是观察者,也是被观察者,这样就构成一条链,一旦建立广播链,逻辑就比较复杂,可维护性非常差。在观察者模式中最多出现一个对象既是观察者也是被观察者。
2:异步处理问题。
在观察者比较多,处理时间比较长时,可以采用异步处理,但是需要考虑线程安全和队列问题。