写博客,看博客,要的是直接进入主题,不要太多的前戏,否则读者看着看着就没了兴趣。
所以直接看设计模式-观察者模式的图示介绍:
所谓的主题,即被观者的对象,当这个对象发生变化的时候,对象发出通知,那么订阅了这个主题的订阅者,会接受到通知并进行相关的操作。订阅者可以订阅多个主题,一个主题也可以被多个订阅者订阅。
注意的是,这个地方的所谓的主题、订阅者、通知,是否是和notify相同呢?答案的非也,notify是esb的一种,涉及到消息中心、发送者、订阅者三个方面,而且消息的发送者是不区分数据是否变更的,而是一旦有需要,就直接发送消息,不同的内容的消息,订阅者订阅特定类型的消息进行处理。
这里我们举一个例子,老王开灰机,灰机的前翅子如果参数异常,就让老王跳机。那么看看代码吧:
飞机的前翅子,也就是被观察的对象:
package com.observer; import java.util.Observable; /** * 灰机的前翅子 * <p> * 观察者模式 - 主题对象 * </p> * @author quzishen */ public class ChiZiInfo extends Observable { //~~~ 飞行参数 private double flyParam; //~~~ 旋转速度 private double speed; //~~~ 温度 private float temperature; //~~~ 是否需要检查 private boolean isNeedCheck = true; /** * 通知订阅者参数变更 */ public void paramChanged(){ setChanged(); notifyObservers(isNeedCheck); } public ChiZiInfo(double flyParam, double speed, float temperature) { super(); this.flyParam = flyParam; this.speed = speed; this.temperature = temperature; } /** * 设置参数 * @param flyParm * @param speed * @param temperature */ public void setParam(double flyParm,double speed,float temperature){ this.flyParam = flyParm; this.speed = speed; this.temperature = temperature; // 当参数改变,触发通知 paramChanged(); } public double getFlyParam() { return flyParam; } public void setFlyParam(double flyParam) { this.flyParam = flyParam; } public double getSpeed() { return speed; } public void setSpeed(double speed) { this.speed = speed; } public float getTemperature() { return temperature; } public void setTemperature(float temperature) { this.temperature = temperature; } }
注意其中的参数变化的时候,是手动触发发送通知的!
飞机的平衡机,也就是观察者
package com.observer; import java.util.Observable; import java.util.Observer; /** * 灰机的平衡装置机 * <p> * 观察者模式 - 观察者 * </p> * @author quzishen * */ public class BalanceMechine implements Observer { //~~~ 灰机的前翅子 private ChiZiInfo chiZiInfo; /** * 初始化 */ public void init(ChiZiInfo chiZiInfo){ // 订阅主题 chiZiInfo.addObserver(this); } public void update(Observable o, Object arg) { // 主题类型判断 if(o instanceof ChiZiInfo){ Boolean isNeedCheck = (Boolean)arg; chiZiInfo = (ChiZiInfo)o; if(isNeedCheck){ //~~~ 飞行参数 double flyParam = chiZiInfo.getFlyParam(); //~~~ 旋转速度 double speed = chiZiInfo.getSpeed(); //~~~ 温度 float temperature = chiZiInfo.getTemperature(); if(flyParam > 100 && speed > 10000 && temperature > 250){ publishMsgToDriver("老王,快跳机!"); } } } } /** * 向飞行员发送信号 * @param msg */ private void publishMsgToDriver(String msg){ // publish the message to driver System.out.println(msg); } }
接收到消息之后,先判断是哪种类型,因为可能订阅者订阅了多种主题。
测试代码:
package com.observer; public class Test { /** * 测试灰行员老王跳机 * @param args */ public static void main(String[] args) { ChiZiInfo chiZiInfo = new ChiZiInfo(0,0,0); BalanceMechine balanceMechine = new BalanceMechine(); balanceMechine.init(chiZiInfo); chiZiInfo.setParam(10, 10, 10); chiZiInfo.setParam(100, 10, 10); chiZiInfo.setParam(101, 10001, 300); } }