观察者模式是一个广播机制的基础,实现1对N的联动,当1发生变化,N跟着相应变化,由此衍生了发布订阅模式,其方式分两种,①强制推送:当1发生变化,强制N也跟着发生变化,②拉的方式,即N方可以自己决定是否接收,只有当N这方有需要时才去获取最新的,不然就算1方变化,N这方也不更新。
观察者接口和具体实现类:
/** *观察者接口 */ public interface Observer { void update(Subject subject);//观察者接收一个推送过来的主题 } //============================ /** *观察者具体实现类 */ public class ObserverImpl implements Observer { private int state; //拥有与主体一致的状态,用于接收订阅的主题内容 public int getState() { return state; } public void setState(int state) { this.state = state; } @Override public void update(Subject subject) { this.state=((ConcreteSubject)subject).getState();//在具体观察者中进行同步状态更新 } }
主题基类和主题具体类
/** * 主体的基类,定义了一些公用方法,没有具体主题,也可以定义成抽象类 */ public class Subject { public List<Observer> list=new ArrayList<Observer>();//在主体方定义一个容器存放注册的观察者 public void registerObserver(Observer obs){ list.add(obs);//注册观察者,即把需要订阅的观察者加进容器中 } public void removeObserver(Observer obs){ list.remove(obs);//移除观察者 } //主题发生变化时,通知所有观察者进行更新 public void notifyAllObservers(List<Observer> list){ for (Observer observer : list) { observer.update(this); } } } //================================================= /** *有具体主题的子类 */ public class ConcreteSubject extends Subject { private int state;//模拟一个具体主题 public int getState() { return state; } public void setState(int state) { this.state = state; this.notifyAllObservers(list);//此步为关键,当主题发生变化时,主题中注册的观察者的状态也跟着进行更新 } }
客户端调用:
public static void main(String[] args) { ConcreteSubject concreteSubject = new ConcreteSubject();//目标主题,发布者 ObserverImpl observer1=new ObserverImpl(); ObserverImpl observer2=new ObserverImpl(); ObserverImpl observer3=new ObserverImpl(); concreteSubject.registerObserver(observer1);//注册观察者 concreteSubject.registerObserver(observer2); concreteSubject.registerObserver(observer3); concreteSubject.setState(1000);//目标主题状态为1000 System.out.println(observer1.getState()); System.out.println(observer2.getState()); System.out.println(observer3.getState());//观察者的值也都为1000 concreteSubject.setState(2000);//目标主题状态值发生改变 System.out.println(observer1.getState()); System.out.println(observer2.getState()); System.out.println(observer3.getState());//观察者的值也改为2000 }
以上代码是自己实现的观察者模式,实际上JavaSE中已经为我们提供了实现观察者模式的基础,java.util.Observable类和java.util.Observer接口,通过这两个对象可以方便的实现观察者模式,java.util.Observable相当于上面定义的Subject,Observable中定义好了一些常用的方法来添加观察者,移除观察者等,观察者只要实现Observer接口就具有观察者身份,可以被添加进来。
/** * 继承JDK的Observable类实现主题 */ public class ConcreteSubject extends Observable{ private int state; public int getState() { return state; } public void setState(int state) { this.state = state; super.setChanged();//当次属性发生改变时,调用基类的setChanged()方法表示当前观察者有改变, //主要改变super.hasChanged()方法返回值,观察者可以通过此值判断目标对象是否已改变 super.notifyObservers(this.state);//把当前发生改变的对象通知各个观察者 } } //=================================================== /** *实现JDK的观察者接口,实现更新方法 */ public class ObserverImpl 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 obj) { setState(((ConcreteSubject)o).getState()); //this.state =Integer.parseInt((String)obj);//也可以直接通过传递过来的参数赋值 } } //================================================== public static void main(String[] args) { ConcreteSubject subject=new ConcreteSubject(); ObserverImpl observer1=new ObserverImpl(); ObserverImpl observer2=new ObserverImpl(); ObserverImpl observer3=new ObserverImpl(); subject.addObserver(observer1); subject.addObserver(observer2); subject.addObserver(observer3); subject.setState(10); System.out.println(observer1.getState()); System.out.println(observer2.getState()); System.out.println(observer3.getState());//观察者的值也都为1000 subject.setState(2000);//目标主题状态值发生改变 System.out.println(observer1.getState()); System.out.println(observer2.getState()); System.out.println(observer3.getState());//观察者的值也改为2000 }
JavaEE中监听器就使用的是观察者模式