一、观察者模式概述
观察者模式主要用于 1 :N 的通知。当一个对象(目标对象 Subject 或 Observable)的状态变化时,它需要通知一系列对象(观察者对象 Observer),令它们做出响应。
通知观察者的方式:
(1)推
每次都会把通知以广播的方式发送给所有观察者,所有观察者只能被动接收。
(2)拉
观察者只要知道有情况即可。至于什么时候获取内容,获取哪些内容,都可以自主决定。
二、观察者模式示例代码
1 /** 2 * 观察者对象接口 3 * @author CL 4 * 5 */ 6 public interface Observer { 7 /** 8 * 更新主题 9 * @param subject 10 */ 11 void update(Subject subject); 12 13 }
1 /** 2 * 主题对象(目标对象) 3 * @author CL 4 * 5 */ 6 public class Subject { 7 8 protected List<Observer> list; 9 10 public Subject() { 11 list = new ArrayList<Observer>(); 12 } 13 14 public void addObserver(Observer observer) { 15 list.add(observer); 16 } 17 18 public void removeObserver(Observer observer) { 19 list.remove(observer); 20 } 21 22 /** 23 * 通知所以观察者更新状态 24 */ 25 public void notifyAllObserver() { 26 for (Observer o : list) { 27 o.update(this); 28 } 29 } 30 31 32 }
1 /** 2 * 具体的目标对象 3 * @author CL 4 * 5 */ 6 public class ConcreteSubject extends Subject { 7 8 /** 9 * 状态 10 */ 11 private int state; 12 13 public int getState() { 14 return state; 15 } 16 17 public void setState(int state) { 18 this.state = state; 19 //若主题对象(目标对象)发生的状态发生改变,请通知所有观察者更新状态 20 this.notifyAllObserver(); 21 } 22 23 }
1 /** 2 * 观察者 3 * @author CL 4 * 5 */ 6 public class ObserverA implements Observer { 7 8 private int myState; //myState需要和目标对象的state保持一致 9 10 @Override 11 public void update(Subject subject) { 12 myState = ((ConcreteSubject) subject).getState(); 13 } 14 15 public int getMyState() { 16 return myState; 17 } 18 19 public void setMyState(int myState) { 20 this.myState = myState; 21 } 22 23 }
测试:
1 /** 2 * 测试观察者模式 3 * @author CL 4 * 5 */ 6 public class Client { 7 8 public static void main(String[] args) { 9 //目标对象 10 ConcreteSubject sub = new ConcreteSubject(); 11 12 //创建三个观察者 13 ObserverA o1 = new ObserverA(); 14 ObserverA o2 = new ObserverA(); 15 ObserverA o3 = new ObserverA(); 16 17 //将这三个观察者添加到目标对象subject的容器中 18 sub.addObserver(o1); 19 sub.addObserver(o2); 20 sub.addObserver(o3); 21 22 //修改目标对象的状态值 23 sub.setState(100); 24 25 System.out.println(o1.getMyState()); 26 System.out.println(o2.getMyState()); 27 System.out.println(o3.getMyState()); 28 29 System.out.println("----------------------"); 30 31 //修改目标对象的状态值 32 sub.setState(10); 33 34 System.out.println(o1.getMyState()); 35 System.out.println(o2.getMyState()); 36 System.out.println(o3.getMyState()); 37 } 38 }
控制台输出:
100 100 100 ---------------------- 10 10 10
三、JDK 中提供类和方法实现观察者模式
1 import java.util.Observable; 2 3 /** 4 * 目标对象 5 * @author CL 6 * 7 */ 8 public class ConcreteSubject extends Observable { 9 private int state; 10 11 public int getState() { 12 return state; 13 } 14 15 public void setState(int state) { 16 this.state = state; 17 18 setChanged(); //表示目标对象已经更改状态 19 20 notifyObservers(); //通知所有观察者 21 } 22 23 }
1 import java.util.Observable; 2 import java.util.Observer; 3 4 /** 5 * 观察者对象 6 * @author CL 7 * 8 */ 9 public class ObserverA implements Observer { 10 11 private int myState; 12 13 @Override 14 public void update(Observable o, Object arg) { 15 myState = ((ConcreteSubject) o).getState(); 16 } 17 18 public int getMyState() { 19 return myState; 20 } 21 22 public void setMyState(int myState) { 23 this.myState = myState; 24 } 25 26 }
测试:
1 /** 2 * 测试利用java.util.*包中的类Observable和接口Obsever实现的观察者模式 3 * @author CL 4 * 5 */ 6 public class Client { 7 8 public static void main(String[] args) { 9 //目标对象 10 ConcreteSubject sub = new ConcreteSubject(); 11 12 //创建三个观察者 13 ObserverA o1 = new ObserverA(); 14 ObserverA o2 = new ObserverA(); 15 ObserverA o3 = new ObserverA(); 16 17 //将这三个观察者添加到目标对象subject的容器中 18 sub.addObserver(o1); 19 sub.addObserver(o2); 20 sub.addObserver(o3); 21 22 //修改目标对象的状态值 23 sub.setState(666); 24 25 System.out.println(o1.getMyState()); 26 System.out.println(o2.getMyState()); 27 System.out.println(o3.getMyState()); 28 29 System.out.println("----------------------"); 30 31 //修改目标对象的状态值 32 sub.setState(123); 33 34 System.out.println(o1.getMyState()); 35 System.out.println(o2.getMyState()); 36 System.out.println(o3.getMyState()); 37 } 38 }
控制台输出:
666 666 666 ---------------------- 123 123 123
四、观察者模式常见开发应用场景
(1)手机APP中每天的推送广告;
(2)多人联机网络游戏中,服务器实时分发所有玩家的状态;
(3)Servlet 中监听器的实现;
(4)Android 中广播机制;
(5)JDK 的 AWT 事件处理模型,基于观察者模式的委派事件模型(Delegation Event Model)
事件源:目标对象
事件监听器:观察者
(6)…………