365体育投注_365bet体育在线—①触*即發

Head First设计模式——观察者模式

前言: 这篇文章365bet体育在线们以Head First设计模式中讲解的气象站为例,通过它的案列进行学分析和编码(C#)测试,并归纳总结出观察者模式。

1、气象监测案列,错误示范实现

一个气象站,分别有三个装置:温度感应装置,湿度感应装置,气压感应装置。WeathData对象跟踪气象站数据,WeathData有MeasurmentsChanged()方法,当感应装置数据变化后就会调用MeasurmentsChanged对使用改数据的用户进行数据更新。目前需求是要三个布告板,分别是目前气象数据状况布告板(CurrentConditionDisply)、气象数据统计布告板(StaisticsDisply)、天气预报布告板(ForcastDisply)。三块布告板都是需要接收气象站数据,然后按需展示到布告板上。针对这个需求365bet体育在线们可以如下方式实现:

public class WeatherData(){
    private float Temperature{get;set;}
    private float Humidity{get;set;}
    private float Pressure{get;set;}

    public void MeasurmentsChanged(){
        CurrentConditionDisply.Update(Temperature,Humidity,Pressure);
        StaisticsDisply.Update(Temperature,Humidity,Pressure);
        ForcastDisply.Update(Temperature,Humidity,Pressure);
    }
}

public class CurrentConditionDisply{
    public void Update(float temperature,float humidity,float Pressure){
        //更新公布数据
    }
}
public class StaisticsDisply{
    public void Update(float temperature,float humidity,float Pressure){
        //更新统计数据
    }
}
public class ForcastDisply{
    public void Update(float temperature,float humidity,float Pressure){
        //更新天气预报
    }
}

 WeatherData是数据跟踪对象,当气象站数据变化时用MeasurmentsChanged方法来依次调用三块布告板的Update方法更新气象数据。按照这种设计能实现目前需求,但是如果新加入365体育投注布告板或者删除一个布告板,那么365bet体育在线们需要去修改MeasurmentsChanged方法新增或者删除代码,这就会造成后期的维护扩展问题。这个例子暴露的问题:

1、365bet体育在线们是针对实现编程,而非针对接口。

2、对于365体育投注新的布告板,365bet体育在线们都得修改代码。

3、无法在运行时动态地增加或者删除布告板。

4、未封装改变的部分,违反了对修改关闭,对扩展开放原则。

2、使用观察者模式解耦

由1的实现和带来的问题以及它的场景365bet体育在线们可以使用设计模式中的观察者模式很好的满足这一需求,且后面的维护扩展都很方便。首先365bet体育在线们先了解观察者模式

观察者模式:定义了对象之间的一对多依赖,当一个对象改变时,他的所有依赖都会收到通知并自动更新。

订阅报纸就是典型的观察者模式,出版社即为主题(subject),订阅者即是观察者(observer),当有新报纸时,报社就会派人送新报纸到订阅了该报纸的读者手上。365bet体育在线们通过观察者模式类图进行理解365bet体育在线记忆,然后365bet体育在线们再对之前的气象站进行观察者模式封装修改。

3、利用观察者模式改进气象站

按照观察者模式365bet体育在线们需要定义一个主题接口Subject,WeatherData作为具体的主题类继承接口Subject,实现注册移除通知观察者接口。定义Observer接口,其他三块布告板继承Observer实现自己的更新数据方法Update。

    /// <summary>
    /// 主题
    /// </summary>
    public interface Subject
    {
        public void RegisterObserver(Observer o);
        public void RemoveObserver(Observer o);
        public void NotifyObserver();
    }
    /// <summary>
    /// 具体主题(气象站)
    /// </summary>
    public class WeatherData : Subject
    {
        private List<Observer> observers;
        private float Temperature { get; set; }
        private float Humidity { get; set; }
        private float Pressure { get; set; }

        public WeatherData()
        {
            observers = new List<Observer>();
        }
        public void RegisterObserver(Observer o)
        {
            observers.Add(o);
        }

        public void RemoveObserver(Observer o)
        {
            observers.Remove(o);
        }

        //通知观察者
        public void NotifyObserver()
        {
            foreach (var o in observers)
            {
                o.Update(Temperature, Humidity, Pressure);
            }
        }

        public void MeasurmentsChanged()
        {
            NotifyObserver();
        }

        //数据变化
        public void SetMeasurments(float temperature, float humidity, float pressure)
        {
            Temperature = temperature;
            Humidity = humidity;
            Pressure = pressure;
            MeasurmentsChanged();
        }
    }

    /// <summary>
    /// 订阅者
    /// </summary>
    public interface Observer
    {
        void Update(float temperature, float humidity, float pressure);
    }

    public class CurrentConditionDisply : Observer
    {
        private Subject weatherData;
        public CurrentConditionDisply(Subject weatherData)
        {
            this.weatherData = weatherData;
            weatherData.RegisterObserver(this);
        }
        public void Update(float temperature, float humidity, float pressure)
        {
            Console.WriteLine($"当前情况布告板:{temperature},{humidity},{pressure}");
        }
    }
    public class StaisticsDisply : Observer
    {
        private Subject weatherData;
        public StaisticsDisply(Subject weatherData)
        {
            this.weatherData = weatherData;
            weatherData.RegisterObserver(this);
        }
        public void Update(float temperature, float humidity, float pressure)
        {
            Console.WriteLine($"统计数据布告板:{temperature},{humidity},{pressure}");
        }
    }
    public class ForcastDisply : Observer
    {
        private Subject weatherData;
        public ForcastDisply(Subject weatherData)
        {
            this.weatherData = weatherData;
            weatherData.RegisterObserver(this);
        }
        public void Update(float temperature, float humidity, float pressure)
        {
            Console.WriteLine($"天气预报布告板:{temperature},{humidity},{pressure}");
        }
    }

对使用了观察者模式的气象站进行测试,当数据变化的时候就会自动通知观察者并更新数据,也可以灵活的添加移除观察者而不用去具体的实现里面修改代码。

        static void Main(string[] args)
        {
            WeatherData weatherData = new WeatherData();
            CurrentConditionDisply currentConditionDisply = new CurrentConditionDisply(weatherData);
            StaisticsDisply staisticsDisply = new StaisticsDisply(weatherData);
            ForcastDisply forcastDisply = new ForcastDisply(weatherData);
            weatherData.SetMeasurments(30, 65, 30.5F);
            Console.WriteLine("---------------移除订阅者-----------");
            weatherData.RemoveObserver(currentConditionDisply);
            weatherData.SetMeasurments(31,55,20);
            Console.WriteLine("---------------添加订阅者-----------");
            weatherData.RegisterObserver(currentConditionDisply);
            weatherData.SetMeasurments(30, 55, 30.5F);
            Console.ReadKey();
        }

  

posted @ 2019-10-22 11:28  Spring2Sun  阅读(...)  评论(...编辑  收藏