模式定义
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,是他们能够自动跟新自己。
观察者模式又称为发布-订阅模式。
模式结构
模式实现
通职者
package com.bjsxt.observer;
public abstract class Subject {
private String action;
public abstract void attach(Observe observe);
public abstract void detach(Observe observe);
public abstract void notifyOfSubject();
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
}
package com.bjsxt.observer;
import java.util.ArrayList;
import java.util.List;
public class Boss extends Subject {
private List<Observe> observers = new ArrayList<Observe>();
public void attach(Observe observe) {
observers.add(observe);
}
public void detach(Observe observe) {
observers.remove(observe);
}
public void notifyOfSubject() {
for(Observe observe : observers){
observe.update();
}
}
}
观察者
package com.bjsxt.observer;
public abstract class Observe {
protected String name;
protected Subject subject;
public Observe(String name, Subject subject) {
this.name = name;
this.subject = subject;
}
public abstract void update();
}
package com.bjsxt.observer;
public class StockObserve extends Observe {
public StockObserve(String name, Subject subject) {
super(name, subject);
}
public void update() {
System.out.println(subject.getAction() + ", " + name + " 关闭股票行情!");
}
}
测试类
package com.bjsxt.observer;
public class Client {
public static void main(String[] args) {
Boss boss = new Boss();
boss.setAction("boss");
StockObserve stockObserve = new StockObserve("威威", boss);
boss.attach(stockObserve);
boss.notifyOfSubject();
}
}
当然对于Java,现在已经提供了现成的观察者模式模板。
Observable
package com.bjsxt.observer2;
import java.util.Observable;
//目标对象
public class ConcreteSubject extends Observable {
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public void set(int s) {
state = s;//目标状态发生了改变
setChanged(); //表示目标对象已做修改
notifyObservers(state); //通知所有的观察者
}
}
Observe
package com.bjsxt.observer2;
import java.util.Observable;
import java.util.Observer;
public class ObserverA implements Observer {
private int state;
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
@Override
public void update(Observable o, Object arg) {
this.state = ((ConcreteSubject)o).getState();
}
}
package com.bjsxt.observer2;
public class Client {
public static void main(String[] args) {
//创建目标对象
ConcreteSubject subject = new ConcreteSubject();
//创建观察者
ObserverA obs1 = new ObserverA();
ObserverA obs2 = new ObserverA();
ObserverA obs3 = new ObserverA();
//将上面三个观察对象添加到目标对象subject的观察者容器中
subject.addObserver(obs1);
subject.addObserver(obs2);
subject.addObserver(obs3);
//修改状态
subject.set(3000);
System.out.println(obs1.getState());
System.out.println(obs2.getState());
System.out.println(obs3.getState());
//再改一次
subject.set(600);
System.out.println(obs1.getState());
System.out.println(obs2.getState());
System.out.println(obs3.getState());
}
}
使用场景
1、一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
2、一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
3、一个对象必须通知其他对象,而并不知道这些对象是谁。需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
模式优缺点
优点:
1、观察者和被观察者是抽象耦合的。
2、建立一套触发机制。
缺点:
1、如果一个观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
2、如果再观察者和观察者目标之间有循环依赖的话,观察者会触发他们之间的循环调用,肯能导致系统奔溃。
3、观察者没有相应的机制让观察者知道所要观察的目标对象发生了什么样的变化,只是知道发生了变化。
模式总结
1、观察模式所做的工作其实就是在解除耦合,让耦合的双方都依赖于抽象而不是具体。从而使得各自的变化都不会影响另一边的变化。
2、观察者模式定义了对象之间的一对多关系。多个观察者监听同一个被观察者,当该被观察者的状态发生改变时,会通知所有的观察者。