观察者模式
观察者模式也叫做发布——订阅模式(Publish/Subscribe)模式。
它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。
这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。
- 代码结构
- Subject类,即主题或者抽象统治者,一般用一个抽象类或者一个接口实现。它把所有对观察者对象的引用保存在一个集合里面,每个主题都可以有任意数量的观察者。
abstract class Subject{
private ArrayList<Observer> Observers=new ArrayList<>();
public void Attach(Observer observer){
Observers.add(observer);
}
public void Detach(Observer observer){
Observers.remove(observer);
}
public void Notify(){
for(int i=0;i<Observers.size();i++){
Observers(i).Update();
}
}
}
- Observer类,即抽象观察者类,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。抽象观察者一般用一个抽象类或者接口实现。
abstract class Observer{
public abstract void Update();
}
- ConcreteSubject类,即具体主题或具体通知者,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。
class ConcreteSubject extends Subject{
private String subjectState;
public void setSubjectState(String state){
this.subjectState = state;
}
public String getSubjectState(){
return this.subjectState;
}
}
- ConcreteObserver类,即具体观察者,实现抽象观察者角色所要求的更新接口,以便时本身的状态与主题的状态相协调,保存一个指向具体主题对象的引用。
class ConcreteObserver extends Observer{
private String name;
private String ObserverState;
private ConcreteSubject subject;
public ConcreteObserver(ConcreteSubject subject,String name){
this.subject = subject;
this.name = name;
}
public void Update(){
observerState = subject.SubjectState;
System.out.println("观察者"+name+"的新状态是"+observerState);
}
}
public static void main(String[]args){
ConcreteSubject s = new ConcreteSubject();
s.Attach(new ConcreteObserver(s,"X"));
s.Attach(new ConcreteObserver(s,"Y"));
s.Attach(new ConcreteObserver(s,"Z"));
s.setSubjectState("ABC");
s.Notify();
}
观察者模式的特点
- 观察者模式的关键对象是主题Subject和观察者Observer,一个Subject可以有任意数目的依赖它的Observer,一旦Subject的状态发生了改变,所有的Observer都可以得到通知。Subject发出通知时并不需要直到谁是它的观察者。
- 使用场景:当一个对象的改变需要同时改变其他对象,而且它不知道具体有多少对象有待改变时,应该考虑使用观察者模式。
- 一个抽象模型有两个方面,其中一方面 依赖于另一方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。
- 观察者模式所作的工作就是在解除耦合。
观察者模式的不足补充
- 由于观察者和通知者之间互相不见面,由客户端来决定通知谁,就能够避免万一没有了抽象观察者接口,通知功能就完成不了;每个具体观察者,不一定是“更新”的方法实现调用——采用事件委托方式来实现。
- 实现方式参考这位博主介绍的还比较清晰