Wednesday, October 17, 2012

Observer Pattern

*Disclaimer these writings are for my own learning purposes not as advice to others. If any part is incorrect please feel free to constructively discuss.

Previously I discussed
Strategy Pattern
Factory Pattern
Abstract Factory Pattern

Due to how events are handled one of the most widely used patterns in the .Net framework is the Observer Pattern.

The main point of the observer pattern is the allow objects to be notify of state change in other objects without being tightly coupled. At least thats how I would describe it to someone in my own words.

A more text book definition is:
"Defines a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically" Got that from OODesigns.

If you ever written an application using the architectural pattern's MVC or MVVM you've used the observer pattern.

As usual I will not go into a lot of detail defining the pattern, there's plenty of sites that have already done that. Below is my example, and here is the source code.

*Note this is a very basic example. I point that out because you can get quite a bit more specific in exactly what flavor of the observer pattern you implement. I believe publish / subscribe is the most widely used. Another is using a feature called an event manager or change manager, or Event Emitter/Target/Dispatcher. My example is a simple publisher / subscriber flavor. Also within that flavor you can implement notifications in a "push" or "pull" manner. Push being the subject always informs the observers of change, and "pull" being the observers can reach out and check for changes in the subject when they want. This example uses the Push technique.

//Subject interface
public interface IEngine
{
      string Name { get; set; }
      List<ISubscriber> Subscribers { get; set; }
      void Notify();
      void Attach(ISubscriber subscriber);
      void Detach(ISubscriber subscriber);
      int EngineTemp { get; set; }
}

//Concrete Subject
public class SilveradoEngine : IEngine
{
        public List<ISubscriber> Subscribers { get; set; }

        public SilveradoEngine()
        {
            Subscribers = new List<ISubscriber>();
        }

        public void Notify()
        {
            foreach(ISubscriber subs in Subscribers)
            {
                subs.Update(this);
            }
        }

        public void Attach(ISubscriber subscriber)
        {
            Subscribers.Add(subscriber);
        }

        public void Detach(ISubscriber subscriber)
        {
            Subscribers.Remove(subscriber);
        }

        private int _EngineTemp;
        public int EngineTemp
        {
            get
            {
                return _EngineTemp;
            }
            set
            {
                _EngineTemp = value;
                Notify();
            }
        }

        public string Name { get; set; }
}

//Observer or subscriber interface
public interface ISubscriber
{
      void Update(SilveradoEngine engine);
}

//Concrete Observer 1
public class EngineTemperatureDashLight : ISubscriber
{
        IEngine engine;
        public EngineTemperatureDashLight()
        {
            this.engine = engine;
        }
        public void Update(SilveradoEngine engine)
        {
            this.engine = engine;
            EngineTempWarningLight = this.engine.EngineTemp > 500 ? true : false;
        }

        public bool EngineTempWarningLight {get; set; }

}

//Concrete Observer 2
public class OnStarAlert : ISubscriber
{
        IEngine engine;
        public OnStarAlert(IEngine engine)
        {
            this.engine = engine;
        }
       
        public void Update(SilveradoEngine engine)
        {
            this.engine = engine;
            OnstartHasAlerts = this.engine.EngineTemp > 500 ? true : false;
        }

        public bool OnstartHasAlerts { get; set; }
}

No comments:

Post a Comment