Preface: in this paper, we take the weather station explained in the Head First design model as an example, through its case analysis and coding (C#) test, and summarize the observer model.

1, meteorological monitoring case, error demonstration

A weather station, each has three devices: temperature sensing device, humidity sensing device, pressure sensing device. The WeathData object tracks weather station data. The WeathData has a MeasurmentsChanged() method that calls MeasurmentsChanged when the sensor data changes to update the data to the user who uses the changed data. At present, three bulletin boards are required, namely, current Condition bulletin board, StaisticsDisply bulletin board, and ForcastDisply bulletin board. All three boards are required to receive weather station data and display it on the board as needed. To meet this requirement, we can implement it as follows:

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){
        // Update the published data}}public class StaisticsDisply{
    public void Update(float temperature,float humidity,float Pressure){
        // Update the statistics}}public class ForcastDisply{
    public void Update(float temperature,float humidity,float Pressure){
        // Update the weather forecast}}Copy the code

WeatherData is a data tracking object that updates the WeatherData by calling the Update method of the MeasurmentsChanged method on each of the three bulletin boards in turn when the weather station data changes. This design will do the job for now, but if a bulletin board is added or removed, then we need to modify the MeasurmentsChanged method to add or remove code, which will cause maintenance extension problems later. The problem this example exposes:

1. We program for implementations, not interfaces.

2. For each new bulletin board, we had to change the code.

Cannot dynamically add or remove bulletin boards at run time.

4. The part that does not encapsulate the change violates the principle of closing for modification and opening for extension.

2. Use observer mode decoupling

With the implementation and problems of 1 and its scenarios, we can use the Observer pattern in the design pattern to meet this requirement well, and the maintenance extension is convenient. First let’s understand the observer pattern

Observer pattern: Defines one-to-many dependencies between objects. When an object changes, all of its dependencies are notified and automatically updated.

Newspaper subscription is a typical observer mode, with the publisher as the subject and the subscriber as the observer. When a new newspaper is available, the newspaper will send someone to deliver the new newspaper to the readers who have subscribed to the newspaper. We understand and memorize the observer model class diagram, and then we modify the observer model encapsulation of the previous weather station.

3. Improve the weather station by using the observer model

According to the observer pattern, we need to define a Subject interface Subject. WeatherData inherits the interface Subject as a specific Subject class to implement the registration of removing notification observer interface. Define the Observer interface. The other three bulletin boards inherit from the Observer to implement their own Update data method.

    /// <summary>
    ///The theme
    /// </summary>
    public interface Subject
    {
        public void RegisterObserver(Observer o);
        public void RemoveObserver(Observer o);
        public void NotifyObserver();
    }
    /// <summary>
    ///Specific Topics (Weather Stations)
    /// </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);
        }
 
        // Notify the observer
        public void NotifyObserver()
        {
            foreach (var o inobservers) { o.Update(Temperature, Humidity, Pressure); }}public void MeasurmentsChanged()
        {
            NotifyObserver();
        }
 
        // Data change
        public void SetMeasurments(float temperature, float humidity, float pressure){ Temperature = temperature; Humidity = humidity; Pressure = pressure; MeasurmentsChanged(); }}/// <summary>
    ///The subscriber
    /// </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(Current Situation bulletin board:{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($" Statistical data board:{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(Weather bulletin board:{temperature}.{humidity}.{pressure}"); }}Copy the code

For weather stations using the observer mode, when the data changes, it will automatically notify the observers and update the data, and it can also flexibly add and remove observers without having to change the code in the implementation.

 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.5 F);
            Console.WriteLine("--------------- remove subscriber -----------");
            weatherData.RemoveObserver(currentConditionDisply);
            weatherData.SetMeasurments(31.55.20);
            Console.WriteLine("--------------- Add subscribers -----------");
            weatherData.RegisterObserver(currentConditionDisply);
            weatherData.SetMeasurments(30.55.30.5 F);
            Console.ReadKey();
        }
Copy the code