观察者模式(observer)
什么是观察者模式:因为面向对象程序的本质是对象之间的相互协作,所以其中一个对象发生变化,另外的某些对象也应该做出相应的动作。观察者模式就是为了应对该情况:对象间存在一种一对多(一对一)的依赖关系,当该对象发生变化时,所有依赖它的对象都得到通知并自动更新。
适用性:对象间存在一种一对多(一对一)的依赖关系。
观察者模式的主要组成: 抽象被观察者、具体被观察者(前两者有时候也可以合并)、抽象观察者、具体观察者。
观察者模式的关键步骤:
抽象被观察者:维护一个观察者容器;变化标志位,表明被观察者是否变化;通知方法,调用所有观察者的update()方法;
具体被观察者:继承抽象被观察者;定义具体观察者变化的方法(包括判断是否变化、设置标志位、通知观察者);
抽象观察者:update()方法;
具体观察者:订阅被观察者;实现update()方法;
观察者模式要点:
抽象被观察者:维护观察者容器、变化标志位、提供注册和注销观察者的方法、通知方法;
具体被观察者:继承抽象、实现对象变化需要通知观察者的方法setDate();
抽象观察者:update()方法;
具体观察者:继承抽象、订阅被观察者、实现update()方法;
观察者模式基本代码:
/*抽象被观察者*/ public abstract class Subject { private Vector<Observer> observers; //保存所有观察者的容器 private boolean changed = false; //是否变化的标志位 public Subject() { this.observers = new Vector<>(); } public void addObserver(Observer obs){ //添加观察者,相当于注册观察者 if(obs == null){ throw new NullPointerException(); } if(!observers.contains(obs)){ observers.add(obs); } } public void deleteObserver(Observer obs){ //删除观察者,相当于注销观察者 observers.removeElement(obs); } public void notifyObservers() { notifyObservers(null); } /** * 如果本对象有变化(那时hasChanged 方法会返回true) * 调用本方法通知所有登记的观察者,即调用它们的update()方法 * 传入this和arg作为参数 */ public void notifyObservers(Object arg) { synchronized (this) { if (!changed) return; } for (Observer obs : observers) obs.update(this,arg); } public synchronized void deleteObservers() { observers.removeAllElements(); } protected synchronized void setChanged() { changed = true; } protected synchronized void clearChanged() { changed = false; } public synchronized boolean hasChanged() { return changed; } public synchronized int countObservers() { return observers.size(); } }
/*观察者接口*/ public interface Observer { //当被观察者发生变化时,会调用观察者的update方法 void update(Subject o, Object arg); }
/*具体被观察者*/ public class ConcreteSubject extends Subject { private String data = ""; public String getData() { return data; } public void setData(String data) { if (!this.data.equals(data)) { this.data = data; setChanged(); //设置改变标志 } notifyObservers(); //通知观察者 } }
/*具体观察者*/ public class ConcreteObserver implements Observer{ public ConcreteObserver(Subject observed){ //订阅,将观察者注册到被观察者 observed.addObserver(this); } @Override public void update(Subject o,Object arg) { //观察者的行为 System.out.println("观察者的行为"); } }
总结:
1 独立改变被观察者和观察者
2 观察者决定是否订阅