Head First Design Patterns - 观察者模式

观察者模式

观察者模式定义了对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。观察者模式是一种对象行为型模式

场景

  • 很多用户都订阅了某一公众号,当该公众号更新时,所以用户都会收到消息。该公众号叫做【主题,Subject】,订阅者叫做【观察者,Observer】。
  • 气象台会将每日更新的天气数据,如温度,气压等,下发给第三方的网站进行显示。气象台被称为【主题,Subject】,不同的第三方网站叫做【观察者,Observer】。书上也是以气象台为例。
    在这里插入图片描述

角色

  • 主题(Subject):指被观察的对象。可以为接口,也可以为抽象类,书中的例子为接口。该接口中一般定义了registerObserver()、removeObserver()、notifyObservers()等方法,作用分别为观察者注册、移除观察者、通知所有的观察者。该类中还会维护一个数据结构来保存所有观察者的引用,书中例子用了List<>,但为了线程安全,一般都用vector<>
  • 具体主题(ConcreteSubject):因为书中的主体定义为接口,因此具体主题类是实现了该主题接口。具体主题也会定义自己的一些逻辑。
  • 观察者(Observer):为接口。定义了update()方法,主题类调用该方法将消息通知到观察者。
  • 具体观察者(ConcreteObserver):维护了一个具体主题对象的引用,方便利用主题的方法进行注册等工作。具体观察者作为Observer的实现类,还实现了update方法。

上述角色可以参考后面的类图。

气象台的实现

气象台的改变逻辑会放在measurementsChanged方法中。

不用设计模式的实现

public class WeatherData {
	public void measurementsChanged() {
		float temp = getTemperature();
		float humidity = getHumidity();
		float pressure = getPressure();
		// 可以理解为更新不同接入气象台网站的显示
		currentConditionDisplay.update(temp, humidity, pressure);
		statisticsDisplay.update(temp, humidity, pressure);
	}
}

以上实现违背了一些设计原则:

  1. 是针对具体的实现,而不是针对接口的实现。没有办法在不修改代码的情况下添加或者移除一些显示元素。
  2. update方法中都是传入几个相同参数,属于主体统一推到观察者的模式没有考虑到网站真正需要什么
  3. 属于硬编码

观察者模式的实现

类图

在这里插入图片描述

示例

  1. 定义主题接口
public interface Subject {
    public void registerObserver(Observer o);

    public void removeObserver(Observer o);

    public void notifyObserver();

}
  1. 实现具体的主题
public class WeatherData implements Subject{
    List<Observer> observerList;
    private float temp; //温度
    private float humidity; //湿度

    private float pressure; //压强

    public WeatherData() {
        observerList = new ArrayList<Observer>();
    }

    @Override
    public void registerObserver(Observer o) {
        observerList.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        observerList.remove(o);
    }
    @Override
    public void notifyObserver() {
        observerList.forEach(Observer::update);
    }

     public void measurementsChanged() {
        notifyObserver();
     }

     public void setMeasurements(float temperatue, float humidity, float pressure) {
        this.temp = temperatue;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
     }

    public float getTemp() {
        return temp;
    }

    public float getHumidity() {
        return humidity;
    }

    public float getPressure() {
        return pressure;
    }
}

  1. 定义观察者接口
public interface Observer {
    void update();
}
  1. 定义展示接口(书中业务的实现,与设计模式没有联系)
public interface DisplayElement {
   public void display();
}
  1. 定义具体的观察者
public class CurrentConditionDisplay implements Observer, DisplayElement{
   private float temp;

   private float humidity;

   private float pressure;

   private WeatherData weatherData;

   public CurrentConditionDisplay(WeatherData weatherData) {
       this.weatherData = weatherData;
       weatherData.registerObserver(this);
   }

   @Override
   public void update() {
       this.temp = weatherData.getTemp();
       this.humidity = weatherData.getHumidity(); // 观察者需要什么,可以从主题中拉取,是属于拉的模式
       this.pressure = weatherData.getPressure();
       this.display();
   }
   @Override
   public void display() {
       System.out.println("current display:" +  temp + " " + humidity + " " + pressure);
   }
  1. 客户端
 public static void main(String[] args) {
     WeatherData weatherData = new WeatherData();

     CurrentConditionDisplay currentConditionDisplay =
             new CurrentConditionDisplay(weatherData);

     weatherData.setMeasurements(80, 65, 30.4f);
 }

输出:
current display:80.0 65.0 30.4 // 例子中只定义了一个观察者

观察者模式所涉及到的设计原则

  • 封装变化。该例子中,变化的是主题的状态、观察者的数量和类型。
  • 针对接口编程而不是针对实现编程。主题跟踪具体的观察者,而观察者通过主题接口来注册并通知。
  • 松耦合。降低了主题和观察者之间的耦合关系,使代码更能应对场景的变化。

应用

spring中的事件驱动模型,具体参考观察者模式

参考文章
观察者模式
设计模式前传

  • 22
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《Head First设计模式-深入浅出设计模式》是一本以简单有趣的方式介绍设计模式的书籍。设计模式是在软件开发中解决特定问题的一种经验总结,它们提供了在实际开发中可重用、可靠、灵活的解决方案。 该书的主要特点是通过生动有趣的讲解和丰富多样的图表、示例来帮助读者更好地理解和应用设计模式。作者采用了大量的图形和实例来解释设计模式的概念,使读者能够迅速理解并应用这些概念。 这本书涵盖了23种常用的设计模式,如工厂模式、单例模式、适配器模式、装饰器模式等。每一种设计模式都以一个实际的例子开始,引出该模式解决的问题,然后详细解释其结构和应用,最后通过示例代码展示如何使用该模式。 此外,该书还介绍了设计模式之间的关系和如何选择合适的设计模式。它教授了读者如何在具体问题中识别出适用的设计模式,并提供了一些实际的应用建议。 《Head First设计模式-深入浅出设计模式》以其独特的教学风格和简洁明了的讲解深受读者喜爱。这本书不仅适合初学者了解设计模式,也适合有一定经验的开发人员进一步提高他们的软件设计和编程能力。 总之,这本书以其生动有趣的讲解方式和大量的图表、实例为读者介绍了设计模式的基本概念和具体应用,是学习和理解设计模式的一本不可或缺的指南。 ### 回答2: 《Head First设计模式:深入浅出设计模式》是一本主要介绍软件设计模式的书籍。设计模式是在软件开发中经常出现的问题的解决方案,可以帮助开发人员更好地构建可重用、可扩展、可维护的代码。 这本书以深入浅出的方式介绍了23种常见的设计模式,通过生动有趣的讲解和大量的图形和实例,使读者能够更加轻松地理解和掌握设计模式。它采用了非传统的学习方式,通过讲故事、练习、谜题等方式将设计模式的概念和使用方法娓娓道来。 该书首先从简单的设计模式开始,引导读者逐步理解和掌握基础的设计原则和模式,如单例模式、工厂模式等。然后,逐渐深入介绍更复杂的模式,如装饰器模式、观察者模式、策略模式等。每个模式都通过具体的案例和代码示例进行讲解,帮助读者理解模式的思想和应用场景。 除了具体的设计模式之外,这本书还关注了如何将设计模式应用到现实的软件开发中。它探讨了如何根据不同的需求选择合适的设计模式,以及如何通过设计模式提高代码的质量和可维护性。 总的来说,《Head First设计模式:深入浅出设计模式》是一本非常有趣、易懂且实用的设计模式入门书籍。无论是初学者还是有一定经验的开发人员,都能从中获得有益的知识和经验,提高软件开发的能力和效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值