观察者模式
观察者模式:定义对象之间的一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都能得到通知并更新状态。观察者模式又被称为发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式等。观察者模式是一种对象行为型模式。
观察者模式UML类图如下:
在观察者模式中有如下几个角色:
- 抽象观察目标Subject:被观察的对象。在抽象观察目标里维护一个保存所有观察者对象引用的集合。它能够增加和删除观察者,同时声明了
notify()
通知观察者。目标可以是接口/抽象类/具体类。 - 具体目标ConcreteSubject:实际被观察对象。当具体目标的状态发生改变时,就会通过notify()通知观察者。
- 观察者接口Observer:被通知的对象。它声明了
update()
当接到通知时用于更新数据。 - 具体观察者ConcreteObserver:实现抽象观察者角色所要求的
update()
方法,使自身状态与Subject状态相协调。也可以维护一个ConcreteSubject的引用。
代码实现如下:
抽象观察目标Subject
import java.util.ArrayList;
import java.util.List;
/**
* 抽象被观察对象Subject
* @author sywyg
* @since 2015.9.6
*/
public abstract class Subject {
private List<Observer> list = new ArrayList<Observer>();
public void registerObserver(Observer o) {
list.add(o);
}
public void removeObserver(Observer o){
list.remove(o);
}
public void notify(int state){
for (Observer observer : list) {
observer.update(state);
}
}
}
具体目标ConcreteSubject
/**
* 具体被观察对象ConcreteSubject
* @author sywyg
* @since 2015.9.6
*
*/
public class ConcreteSubject extends Subject {
private int state;
/**
* 具体被观察目标改变状态
* @param state
*/
public void stateChange(int state) {
// 做些其他的事情,之后通知观察者
this.notify(state);
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
}
观察者接口Observer
/**
* 观察者接口Observer
* @author sywyg
* @since 2015.9.6
*
*/
public interface Observer {
public void update(int state);
}
具体观察者ConcreteObserver
/**
* 具体观察者ConcreteObserver:A
* @author sywyg
* @since 2015.9.6
*
*/
public class ConcreteObserverA implements Observer {
@Override
public void update(int state) {
System.out.println("被观察目标的状态改为:" + state);
}
}
客户端
/**
* 测试程序
* @author sywyg
* @since 2015.9.6
*
*/
public class Client {
public static void main(String[] args) {
// 创建具体被观察对象
ConcreteSubject subject = new ConcreteSubject();
Observer observer = new ConcreteObserverA();
// 添加具体观察者
subject.registerObserver(observer);
// 具体观察对象状态改变
subject.stateChange(2);
}
}
观察者两种方式
推方式
被观察对象直接向观察者推送详细信息,不管是否需要,上面的例子就是这种方式。
拉方式
被观察对象在通知观察者时,将对象的引用传递给观察者,观察者可以通过自身需求来索取相应改变数据。
其实在java API中给我们提供好了观察者模式对象:java.util.Observable
(实现类)和java.util.Observer
(接口),我们也可以使用这个来实现观察者模式。
使用场景
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
- 一个对象必须通知其他对象,而并不知道这些对象是谁。需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象等等,可以使用观察者模式创建一种链式触发机制。
优缺点
优点
1.当两个对象之间松耦合,他们依然可以交互,但是不太清楚彼此的细节。观察者模式提供了一种对象设计,让被观察对象和观察者之间松耦合。
- 观察者模式符合开闭原则的要求。
缺点
- 如果被观察对象有很多观察者,则通知所有的观察者会花费很多时间。
- 如果在被观察对象和观察者之间有循环依赖关系,被观察对象会触发它们之间进行循环调用,可能导致系统崩溃。
- 没有相应的机制让观察者知道被观察对象是怎么发生变化的,而仅仅知道观察目标发生了变化。