Design Patterns: Observer

The observer design pattern can be used when you want objects to know when something happens to an object being observed.

This is done with a Subject and an Observer.

For example, let's say we have a Dragon that will be the subject and then have people as observers. When the dragon switches to a flying mode the observers will look up instead of forward.

To accomplish that we need an ISubject that will have the method to add, remove and notify observers.

  1. public interface IDragonSubject   
  2. {   
  3.    void Subscribe(IDragonObserver observer);   
  4.    void Unsubscribe(IDragonObserver observer);   
  5.    void Notify();   
  6. }   
And the specification for the observers as in the following:
  1. public class Dragon : IDragonSubject    
  2. {    
  3.     private IList<IDragonObserver> observers;    
  4.      
  5.     private bool flying;    
  6.     public bool Flying    
  7.     {    
  8.         get { return flying; }    
  9.         set    
  10.         {    
  11.             if (flying != value)    
  12.             {    
  13.                 flying = value;    
  14.                 Notify();    
  15.             }    
  16.         }    
  17.     }    
  18.      
  19.     public Dragon()    
  20.     {    
  21.         observers = new List<IDragonObserver>();    
  22.     }    
  23.      
  24.     // People around will begin to watch this dragon    
  25.     public void Subscribe(IDragonObserver observer)    
  26.     {    
  27.         observers.Add(observer);    
  28.     }    
  29.      
  30.     // if they get out of range we could unsubscribe    
  31.     public void Unsubscribe(IDragonObserver observer)    
  32.     {    
  33.         observers.Remove(observer);    
  34.     }    
  35.      
  36.     // when something happens we will notify    
  37.     // all observers for this instance    
  38.     public void Notify()    
  39.     {    
  40.         foreach (var observer in observers)    
  41.         {    
  42.             observer.Update(this);    
  43.         }    
  44.     }    
  45. }  
And our observer:
  1. public class Person : IDragonObserver    
  2. {    
  3.     public enum LookingDirectionTypes    
  4.     {    
  5.         Foward,    
  6.         Up,    
  7.         Down,    
  8.         Left,    
  9.         Right,    
  10.     }    
  11.      
  12.     public LookingDirectionTypes LookingDirection { getset; }    
  13.      
  14.     public void Update(Dragon dragon)    
  15.     {    
  16.         if (dragon.Flying)    
  17.             LookingDirection = Person.LookingDirectionTypes.Up;    
  18.         else    
  19.             LookingDirection = LookingDirectionTypes.Foward;    
  20.     }    
  21. }  
Finally, we can put all the pieces together and see the result. In this test there are a couple of people observing the dragon, the third one is elsewhere. So when the dragon starts flying person1 and person2 will look up.
  1. [TestClass]    
  2. public class ObserverTest    
  3. {    
  4.     [TestMethod]    
  5.     public void DragonFlyPeopleLookUp()    
  6.     {    
  7.         Dragon dragon = new Dragon();    
  8.      
  9.         // default looking direction = Foward    
  10.         Person p1 = new Person();    
  11.         Person p2 = new Person();    
  12.         Person p3 = new Person();    
  13.      
  14.         // p1 and p2 are now watching the dragon    
  15.         dragon.Subscribe(p1);    
  16.         dragon.Subscribe(p2);    
  17.      
  18.         // the dragon started to fly    
  19.         dragon.Flying = true;    
  20.      
  21.         Assert.AreEqual(Person.LookingDirectionTypes.Up, p1.LookingDirection);    
  22.         Assert.AreEqual(Person.LookingDirectionTypes.Up, p2.LookingDirection);    
  23.      
  24.         Assert.AreEqual(Person.LookingDirectionTypes.Foward, p3.LookingDirection);    
  25.     }    
  26. }   
A real-life example is on Assassins Creed. Ordinary people are the observers and the assassin is the subject. When the subject tosses money all observers are notified that the action happened and if they are in range they will take an action.