• 设计模式之观察者模式


     什么是观察者模式

    它定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知。

    设计原则

    为了交互对象之间的松藕合设计而努力:松耦合的设计之所以能让我们建立有弹性的OO系统,能够应对变化,是因为对象之间的互相依赖降到了最低。

    图解观察者模式

    一个新的对象需要订阅:当有一个新的需要订阅的对象时,需要先向主题对象调用注册接口注册订阅信息。

     

     新的订阅者:有了新的订阅者后,主题对象将向订阅者4也推送订阅消息 。

    数据更新:一旦数据有更新,将向所有订阅者更新信息 。

    有订阅者需要离开:有订阅者需要离开时,将该订阅者在订阅者列表中移除。

    离开后:不再向离开的订阅者推送消息。

    例子

    现在有一个气象站和布告站(湿度,温度,气压),WeatherData对象(获取气象站数据,更新布告站),我们的工作就是建立一个应用,利用WeatherData对象取得数据,并更新三个布告板:目前状况,气象统计和天气预报。

    定义观察者模式:类图

     设计气象站

    实现气象站

    主题接口:

    public interface Subject
    {
    void registerObserver(Observer o);//注册
    void removeObserver(Observer o);//删除
    void notifyObservers();//改变状态通知
    }

    观察者接口:

    public interface Observer
    {
    /// <summary>
    /// 当气象观察者改变时,主题把这些状态值当作方法参数,传送给观察者。所有观察者都是实现此方法。
    /// </summary>
    void update(float temp, float humidity, float pressure);
    }

    显示接口(非必需):

    public interface DisplayElement
    {
    void display();//当布告栏需要显示时,调用此方法
    }

    主题对象:

    public class WeatherData : Subject//实现主题接口
    {
    private List<Observer> observers;//用来记录观察者
    private float temperature;
    private float humidity;
    private float pressure;
    public WeatherData()
    {
    observers = new List<Observer>();
    }
    public void registerObserver(Observer o)//注册观察者时,添加
    {
    observers.Add(o);
    }
    public void removeObserver(Observer o)//注销观察者时,删除
    {
    observers.Remove(o);
    }
    public void notifyObservers()//把消息通知所有观察者,因为它们都实现了update
    {
    foreach (Observer Observer in observers)
    {
    Observer.update(temperature, humidity, pressure);
    }
    }
    public void measurementChanged()//更新数据,通知观察者
    {
    notifyObservers();
    }
    public void setMeasurements(float temp, float humidity, float pressure)
    {
    this.temperature = temp;
    this.humidity = humidity;
    this.pressure = pressure;
    measurementChanged();
    }
    
    }

    观察者对象:

    public class CurrentConditionsDisplay : Observer, DisplayElement//实现观察者接口和显示接口
    {
    private float temperature;
    private float humidity;
    private Subject weatherDate;
    public CurrentConditionsDisplay(Subject weatherDate)
    {
    this.weatherDate = weatherDate;
    weatherDate.registerObserver(this);//在构造方法中注册(订阅)
    }
    public void display()
    {
    Console.WriteLine($"temperature:{temperature},humidity:{humidity}");
    }
    public void update(float temp, float humidity, float pressure)//当此方法被调用时,更新温度和湿度并显示
    {
    this.temperature = temp;
    this.humidity = humidity;
    display();
    }
    }

    测试:

    static void Main(string[] args)
    {
    WeatherData weatherData = new WeatherData();//建立一个主题对象
    CurrentConditionsDisplay currentConditions = new CurrentConditionsDisplay(weatherData);//注册(订阅)
    //模拟数据
    weatherData.setMeasurements(80, 54, 34);
    weatherData.setMeasurements(1, 2, 3);
    weatherData.setMeasurements(12, 23, 34);
    Console.ReadKey();
    }

    运行结果:

  • 相关阅读:
    Python
    12C配置EM Express的https端口
    在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误
    Java – How to add days to current date
    Java – Display all ZoneId and its UTC offset
    Java 8 – Period and Duration examples
    Java 8 – Convert Instant to ZonedDateTime
    Java 8 – Convert Instant to LocalDateTime
    Java 8 – How to format LocalDateTime
    how-to-convert-string-to-localdate
  • 原文地址:https://www.cnblogs.com/Tan-sir/p/8124250.html
Copyright © 2020-2023  润新知