观察者模式-《Head First 设计模式》第二章

来源:互联网 发布:ysl高仿包包淘宝 编辑:程序博客网 时间:2024/06/08 00:01

问题汇总

  1. 定义
  2. 设计原则四:交互对象之间松耦合设计
  3. 如何使用?
  4. Java内置Observable(被观察者)缺点
  5. 观察者模式是如何利用设计原则的?

  • 问题汇总
  • 观察者模式
    • 1-定义
    • 2-设计原则四交互对象之间松耦合设计
    • 3-优点
    • 4-实例天气气象站数据在多个公告板的展示
      • WetherDateSubject
      • Obeserver
      • 天气测量测试
    • 5-实例利用Java内置观察者模式实现本文实例
      • 被观察者Observerable发出通知的方法
      • 观察者如何获取数据
      • JavaWetherData
      • JavaDisplayEnglish
      • 数据测试
    • 6-Java内置Observable缺点
    • 7-观察者模式是如何利用设计原则的
      • 针对接口编程
      • 多组合少继承

观察者模式


观察者模式是JDK中使用最多的模式。

观察者模式类似于报社的运行方式,订阅者一开始在报社考起了订阅服务,当报社每天获得新报纸之后,会给所有用户派送报纸,如果用户不想继续看报纸了,也可以去报社退订。这种就是观察者模式:

出版者 + 订阅者 = 观察者模式

出版者就是主题Subject,订阅者就是观察者Observer

Subject + Observer = 观察者模式

1-定义

定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并且自动更新。

2-设计原则四:交互对象之间松耦合设计

3-优点

  1. Subject拥有数据并读取,不需要让多个Object操作同一份数据,干净安全
  2. 可以独立的复用Subject和Observer

4-实例:天气气象站数据在多个公告板的展示

结构:天气气象站就是Subject,当数据变动时,通知所有公告牌进行显示。公告牌就是Observer,设计一个Observer接口和element接口(抽象公告牌的共同部分)。

WetherDate(Subject)

public interface Subject {    public void registerObserver(Observer observer);    public void removeObserver(Observer observer);    public void notifycation();}public class WetherData implements Subject{    float temp = 0;    float humidity = 0;    boolean isChanged = false;    ArrayList<Observer> observerList = new ArrayList<>();    //注册观察者就是在链表中添加观察者    public void registerObserver(Observer observer) {        observerList.add(observer);    }    //移除观察者     public void removeObserver(Observer observer) {        int index = observerList.indexOf(observer);        observerList.remove(index);    }    //通知所有观察者    public void notifycation() {        if(isChanged) {            for(Observer observer:observerList) {                observer.update(temp, humidity);            }            isChanged = false;        }    }    public void measureDataChanged(float temp, float humidity) {        this.temp = temp;        this.humidity = humidity;        isChanged = true;        notifycation();    }}

Obeserver

//观察者接口public interface Observer {    public void update(float temp, float humidity);}//告示牌通用功能public interface DisplayElement {    public void display();}//中文版告示牌public class DisplayChinese implements Observer, DisplayElement{    float temp = 0;    float humidity = 0;    public DisplayChinese(WetherData wetherData) {        wetherData.registerObserver(this);    }    public void display() {        System.out.println("中文数据:当前温度:"+temp+"℃/当前湿度:"+humidity+"%");    }    public void update(float temp, float humidity) {        this.temp = temp;        this.humidity = humidity;        display();    }}//英文版告示牌public class DisplayEnglish implements Observer, DisplayElement{    float temp = 0;    float humidity = 0;    public DisplayEnglish(WetherData wetherData) {        wetherData.registerObserver(this);    }    public void display() {        System.out.println("English data:temp:"+temp+"℃/humi:"+humidity+"%");    }    public void update(float temp, float humidity) {        this.temp = temp;        this.humidity = humidity;        display();    }}

天气测量(测试)

public class WetherMeasure {    public static void main(String[] args) {        WetherData wetherData = new WetherData();        DisplayEnglish beijingDisplay = new DisplayEnglish(wetherData);        DisplayChinese nanjingDisplay = new DisplayChinese(wetherData);        wetherData.measureDataChanged(20, 60);    }}

运行结果:

English data:temp:20.0℃/humi:60.0%
中文数据:当前温度:20.0℃/当前湿度:60.0%

  • 可以看到结果显示正确

5-实例:利用Java内置观察者模式,实现本文实例

Java内置支持观察者模式,在包java.util.Observable中。
在Java中,Subject用Observable表示,意思可以理解为被观察者。而观察者依然是Observer

被观察者(Observerable)发出通知的方法

  1. 先调用setChanged()方法
  2. 调用notifyObservers()

观察者如何获取数据

与我们实现的方法不同,Java内置观察者的方法是观察者去主动获取数据。比如在update中去get数据,而不是由被观察者来推送数据。

JavaWetherData

public class JavaWetherData extends Observable{    float temp = 0;    float humi = 0;    //提供获取数据接口    public float getTemp() {        return temp;    }    public float getHumi() {        return humi;    }    public void measureData(float temp, float humi) {        this.temp = temp;        this.humi = humi;        setChanged(); //改变标志        notifyObservers();//推送通知    }}

JavaDisplayEnglish

实现Java提供的Observer接口

public class JavaDisplayEnglish implements Observer, DisplayElement{    float temp = 0;    float humi = 0;    public JavaDisplayEnglish(Observable observable) {        observable.addObserver(this); //在被观察者中进行注册    }    public void display() {        System.out.println("(Java内置观察者)English data:temp:"+temp+"℃/humi:"+humi+"%");    }    //更新数据-主动去获取数据    public void update(Observable arg0, Object arg1) {        if(arg0 instanceof JavaWetherData) { //确保参数正确            JavaWetherData wetherData = (JavaWetherData)arg0;            temp = wetherData.getTemp();            humi = wetherData.getHumi();            display();        }    }}

数据测试

JavaWetherData javaWetherData = new JavaWetherData();JavaDisplayEnglish javaDisplayEnglish = new JavaDisplayEnglish(javaWetherData);javaWetherData.measureData(23, 79);

(Java内置观察者)English data:temp:23.0℃/humi:79.0%

结果正确,这样就实现了观察者模式。但是这种方法是有缺陷的。

6-Java内置Observable缺点

  • Observable是一个类而不是interface,影响了复用和使用。
  • 违反了多用组合,少用继承的原则。

7-观察者模式是如何利用设计原则的?

1.针对接口编程

Observer观察者利用主题的接口向Subject进行注册。
Subject使用Observer的接口通知观察者

2.多组合少继承

对象之间的关系不是通过继承产生,而是在运行时通过组合来产生。

原创粉丝点击