Article2 - Observer Pattern

来源:互联网 发布:程序员用什么软件编程 编辑:程序博客网 时间:2024/05/22 06:47

// This pattern defines a one-to-many dependency between objects so that when one object changes state,
// all its dependents are notified and updated automatically.
// Further, if use template to parameterize the type of class, we can get a more flexible implementation.

Here, I give a C# version implementation.

using System;
using System.Collections.Generic;
using System.Text;

namespace Observer
{
 // subject.cs
    interface ISubject
    {
        void RegisterObserver(Observer o);
        void RemoveObserver(Observer o);
        void NotifyObservers();
    }

    class WeatherStation : ISubject
    {
        public void RegisterObserver(Observer o)
        {
            if (o is Observer)
            {
                if (!listeners.Contains(o))
                    listeners.Add(o);
            }
        }

        public void RemoveObserver(Observer o)
        {
            if (o is Observer)
                listeners.Remove(o);
        }

        public void NotifyObservers()
        {
            if (isChanged)
            {
                foreach (Observer o in listeners)
                    o.Update(temperature, humidity, pressure);
            }
            isChanged = false;
        }

        private void SetChanged()
        {
            isChanged = true;
        }

        public float GetTemperature()
        {
            return temperature;
        }

        public float GetHumidity()
        {
            return humidity;
        }

        public float GetPressure()
        {
            return pressure;
        }

        public void SetElements(float t, float h, float p)
        {
            temperature = t;
            humidity = h;
            pressure = p;
            SetChanged();
            NotifyObservers();
        }

        public WeatherStation()
        {
            listeners = new List<Observer>();
            temperature = 0;
            humidity = 0;
            pressure = 0;
            isChanged = false;
        }

        private List<Observer> listeners;
        private float temperature;
        private float humidity;
        private float pressure;
        private bool isChanged;
    }

 // Observer.cs

  interface Observer
    {
        void Update(float t, float h, float p);

    }

    interface DisplayElement
    {
        void Display();
    }

    class ObserverOne : Observer, DisplayElement
    {
        public ObserverOne(ISubject s)
        {
            temperature = 0;
            humidity = 0;
            aSubject = s;
            aSubject.RegisterObserver(this);
        }
 
     public void Update(float t, float h, float p)
        {
            temperature = t;
            humidity = h;
      Display();
     }

     public void Display()
        {
      Console.WriteLine("ObserverOne: Temperature: {0}/tHumidity: {1}", temperature, humidity);
     }

        public void RegisterMyself()
        {
            aSubject.RegisterObserver(this);
        }

        public void RemoveMyself()
        {
            aSubject.RemoveObserver(this);
        }

     private float temperature;
     private float humidity;
        private ISubject aSubject;
    }

    class ObserverTwo : Observer, DisplayElement
    {
        public ObserverTwo(ISubject s)
        {
            temperature = 0;
            pressure = 0;
            aSubject = s;
            aSubject.RegisterObserver(this);
        }
 
        public void Update(float t, float h, float p)
        {
            temperature = t;
            pressure = p;
      Display();
     }

     public void Display()
        {
      Console.WriteLine("ObserverTwo: Temperature: {0}/tPressure: {1}", temperature, pressure);
     }

                public void RegisterMyself()
        {
            aSubject.RegisterObserver(this);
        }

        public void RemoveMyself()
        {
            aSubject.RemoveObserver(this);
        }

     private float temperature;
     private float pressure;
        private ISubject aSubject;
    }

 // main program
 class Program
    {
        static void Main(string[] args)
        {
            WeatherStation aData = new WeatherStation();
            ObserverOne aOne = new ObserverOne(aData);
            ObserverTwo aTwo = new ObserverTwo(aData);

            aData.SetElements(23.0f, 10.1f, 0.7f);
           
            aOne.RemoveMyself();
            aTwo.RegisterMyself();
            aOne.RegisterMyself();

            aData.SetElements(18.0f, 7.7f, 0.3f);
        }
    }
}

 

Either an interface implemetation or an inheritance impplemetation is still imperfect. Both of them have some flaws. For details pls refer to "Head First Design Pattern" chapter2.