Theme index -- Keyboard shortcut: 'u'  Previous theme in this lecture -- Keyboard shortcut: 'p'  Next slide in this lecture -- Keyboard shortcut: 'n'Operators, Delegates, and Events

A complete PDF version of the text book is now available. The PDF version is an almost complete subset of the HTML version (where only a few, long program listings have been removed). See here.

24.  Patterns and Techniques

In this section we will discuss the Observer design pattern. We have already introduced the idea of design patterns in Chapter 16 and we have studied one such pattern, Singleton, in Section 16.3

24.1 The observer design pattern24.2 Observer with Delegates and Events
 

24.1.  The observer design pattern
Contents   Up Previous Next   Slide Annotated slide Aggregated slides    Subject index Program index Exercise index 

The Observer is often used to ensure a loose coupling between an application and its user interface

In general, Observer can be used whenever a set of observer objects need to be informed about state changes in a subject object

Imagine that a weather service object collects information about temperature, rainfall, and air pressure. When the weather conditions change significantly, a number of weather watcher objects - temperature watchers, rain watchers, general news watchers (newspapers and television stations) will have to be updated. See Figure 24.1.

Figure 24.1    The subject (weather service object) to the left and its three observers (weather watcher objects) to the right. The Weather Service Object get its information various sensors.

The following questions are relevant:

  1. Do the weather service object know about the detailed needs of the weather watcher objects?
  2. How do we associate weather watcher objects with the weather service object?

In most naive solutions, the weather service object forwards relevant sensor observations to the weather watcher objects. The weather service object sends individual and customized messages to each weather watcher object with weather update information which is relevant for the receiver. Thus, the weather service object knows a lot about the individual needs of the watcher objects. This may work for the first two, three, or four watchers, but this approach becomes very problematic if there are many watchers: Every time a new watcher shows up we must change the weather service object.

Now let us face the second issue. In the naive solution, the weather service object will often hard wire the knowledge about watchers in the program. This is probably OK for one, two or three watchers, but it is - of course - tedious in case there are hundreds of watchers.

There is a noteworthy a solution to the problem outlined above. It is described as a design pattern, because it addresses a non-trivial solution to a frequently occurring problem. The design pattern is know as Observer. The key ideas are:

  1. Watcher objects subscribe to updates from the service object.
  2. The service object broadcasts notifications about changes to watchers.
  3. The watcher object may request details from the service object if they need to.

Below, in Program 24.1 and Program 24.2, we show the general idea/template of the Observer pattern.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using System.Collections;
namespace Templates.Observer {

 public class Subject {                             
   // Subject instance variables

   private ArrayList observers = new ArrayList();   

   public void Attach(Observer o){                  
     observers.Add(o);
   }

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

   public void Notify(){                            
     foreach(Observer o in observers) o.Update();   
   }                                                

   public SubjectState GetState(){                  
     return new SubjectState();                     
   }                                                
 }

 public class SubjectState {                        
   // Selected state of the subject
 }
}
Program 24.1    Template of the Subject class.

The weather service object corresponds to an instance of class Subject in Program 24.1 and the watcher objects correspond to observers, as shown in Program 24.2. In Program 24.3 we illustrate how the Observer and Subject classes can be used in a client program. The programs are compilable C# programs, without any substance, however. In an appendix - Section 58.2 - we show the weather service program and how it uses the Observer pattern.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System.Collections;
namespace Templates.Observer {

 public class Observer {                      

   private Subject mySubject;                 
                                              
   public Observer (Subject s){               
     mySubject = s;
   }   

   public void Update(){                      
      // ...                                  

      SubjectState state = mySubject.GetState();   
                                                   
      //   if (the state is interesting){
      //      react on state change
      //   }
   }
 }
}
Program 24.2    A templates of the Observer class.

In Program 24.3 we see that two observers, o1 and o2, are attached to the subject object (line 10 and 11). The third observer o3 is not yet attached. o1 and o2 hereby subscribe to updates from the subject object. Let us now assume that a mutation of the state in the subject object triggers a need for updating the observers. The following happens:

  1. The subject sends a Notify message to itself. (In Program 24.3 the client of Subject and Observer sends the Notify message. This is an artificial and non-typical situation).
  2. Notify updates each of the attached observers, by sending the parameterless Update message. This happens in line 18 of Program 24.1 .
  3. The Update method in the Observer class asks (if necessary) what really happened in the Subject This is done by sending the message GetState back to the subject , see line 13 of Program 24.2 . Individual observers may request different information from the Subject . Some observers may not need to get additional information from the subject, and these observers will therefore not send a GetState message.
  4. GetState returns the relevant information to the observer. The observer does whatever it finds necessary to update itself based on its new knowledge.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using Templates.Observer;
class Client {

  public static void Main(){
     Subject subj = new Subject();                                      
     Observer o1 = new Observer(subj),                                  
              o2 = new Observer(subj),
              o3 = new Observer(subj);

     subj.Attach(o1);  // o1 subscribes to updates from subj.            
     subj.Attach(o2);  // o2 subscribes to updates from subj.

     subj.Notify();    // Following some state changes in subj
                       // notify observers.
  }
}
Program 24.3    Application of the Subject and Observer classes.

You should consult the appendix - Section 58.1 (only on web) - for a more realistic scenario in terms of the weather service and watchers.

 

24.2.  Observer with Delegates and Events
Contents   Up Previous Next   Slide Annotated slide Aggregated slides    Subject index Program index Exercise index 

The Observer idea, as described in Section 24.1 can be implemented conveniently by use of events. We introduced events in Chapter 23.

According to Observer, the subject has a list of observers which will have to notified when the state of the subject is updated. We can can represent the list of observers as an event. Recall from Section 23.2 that an event can contain a number of methods (all of which share a common signature described by a delegate type). Each observer adds a method to the event of the subject object. The subject notifies the observers by triggering the event.

In Program 24.4 we show a template of the Subject class, corresponding to Program 24.1 in Section 24.1. The event is declared in line 9. The delegate type of the event is shown in line 4. Notice that the subscription methods AddNotifier and RemoveNotifier simply adds or subtracts a method to the event. Upon notification - see line 20 in the Notify method - the subject triggers the event. For illustrative purposes - and in order to stay compatible with the setup in Program 24.4, we pass an instance of the subject state to the observer, see line 20 of Program 24.4. In this way there is no need for the observer to ask for it afterwards.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using System.Collections;
namespace Templates.Observer {

 public delegate void Notification(SubjectState ss);

 public class Subject {
   // Subject instance variable

   private event Notification observerNotifier;

   public void AddNotifier(Notification n){
     observerNotifier += n;
   }

   public void RemoveNotifier(Notification n){
     observerNotifier -= n;
   }

   public void Notify(){
     observerNotifier(new SubjectState());
   }
 }

 public class SubjectState {
   // Selected state of the subject
 }
}
Program 24.4    Template of the Subject class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using System.Collections;
namespace Templates.Observer {

 public class Observer {

   public Observer (){
     // ...
   }   

   public void Update(SubjectState ss){
      //   if (the state ss is interesting){
      //      react on state change
      //   }
   }   

 }
}
Program 24.5    Template of the Observer class.

In line 10-11 of Program 24.6 we see that the two observers o1 and o2 add their Update (instance) methods to the subject. This will add these methods to the event. The Update method of the Observer class is seen in line 10-14 of Program 24.5.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using Templates.Observer;
class Client {

  public static void Main(){
     Subject subj = new Subject();
     Observer o1 = new Observer(),
              o2 = new Observer(),
              o3 = new Observer();

     subj.AddNotifier(o1.Update);   
     subj.AddNotifier(o2.Update);   
                                    
     subj.Notify();    
  }
}
Program 24.6    Application of the Subject and Observer classes.

In an appendix - Section 58.2 - we show a version of the weather center and weather watcher program programmed with events.

Generated: Monday February 7, 2011, 12:16:22
Theme index -- Keyboard shortcut: 'u'  Previous theme in this lecture -- Keyboard shortcut: 'p'  Next slide in this lecture -- Keyboard shortcut: 'n'