UML类图
使用场景
对象B会随着对象A的状态的改变而改变,此时可使用观察者模式,即B作为观察者,A作为通知者,为了让通知者不耦合观察者,所以一般而言都会将观察者抽象。值得注意的是,当B随着A的状态的改变而改变时,C随着B的状态的改变而改变时,当D随着C的状态的改变而改变时,,,即这样的关系比较长时,若中间一个结点出现问题会导致后面其他结点后面的状态不能正常变化,这时一般用异步。
代码实现
通知者抽象
//通知者中使用一个集合存放所有观察者对象
import java.util.ArrayList;
import java.util.List;
public abstract class Subject {
private List<Observer> observers = new ArrayList<Observer>();
public void attach(Observer observer){
observers.add(observer);
}
public void dettach(Observer observer){
observers.remove(observer);
}
public void awake(){
for (Observer observer : observers) {
observer.update();
}
}
}
观察者抽象
//抽象的方法中应该具有更新状态的抽象方法
public abstract class Observer {
public abstract void update();
}
通知者的具体实现
//通知者中应该有自己的状态字段
public class ConcreteSubject extends Subject{
private String subjectState;
public String getSubjectState(){
return subjectState;
}
public void setSubjectState(String subjectState){
this.subjectState = subjectState;
}
}
观察者具体实现
public class ConcreteObserver extends Observer{
//观察者自身的特殊字段
private String name;
//观察者的状态
private String observerState;
//具体的通知者,需要该字段主要是为了在update中获取通知者的状态
private ConcreteSubject subject;
public ConcreteObserver(ConcreteSubject subject,String name){
this.subject = subject;
this.name = name;
}
@Override
public void update(){
this.observerState = this.subject.getSubjectState();
System.out.println(String.format("观察者%s的新状态是%s",this.name,this.observerState));
}
public void setSubject(ConcreteSubject subject){
this.subject = subject;
}
public ConcreteSubject getSubject(){
return subject;
}
}
Main客户端
public class Main {
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.awake();
}
}
输出
观察者X的新状态是ABC
观察者Y的新状态是ABC
观察者Z的新状态是ABC
注意
现在是ConcreteObserver观察ConcreteSubject,当还存在ConcreteObserver2需要随着ConcreteObserver的状态的改变而改变时,那么只需ConcreteObserver继承Subject,让ConcreteObserver2继承Observer即可,从而可让ConcreteObserver作为通知者通知ConcreteObserver2。在java中由于没有多继承,此时需要将Observer修改成接口。