<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Programming tidbits: store &amp; retrieve : Design patterns</title><link>http://blogs.msdn.com/oanapl/archive/tags/Design+patterns/default.aspx</link><description>Tags: Design patterns</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Design patterns: How do you notify components about events that happen in different components?</title><link>http://blogs.msdn.com/oanapl/archive/2009/07/03/design-patterns-iobservable-and-iregistrar.aspx</link><pubDate>Fri, 03 Jul 2009 03:57:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9815496</guid><dc:creator>OanaPlaton</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/oanapl/comments/9815496.aspx</comments><wfw:commentRss>http://blogs.msdn.com/oanapl/commentrss.aspx?PostID=9815496</wfw:commentRss><description>&lt;P&gt;I recently had to solve these kind of requirements: some components execute actions and at some point in time need to notify other components that certain events happened, so the other components can execute code related to these events. For example, class A executes method ChangeStateOfObjectX, and needs to notify class B when X is changed; then B does a certain action (for example, increments a perf counter that illustrates the number of inner objects in X, or writes an event entry or plays a song) when it’s notified. Let’s call class A the Events Generator (because it generates events :)) and B the Events Consumer (because it takes actions in response to the events generated by A). &lt;/P&gt;
&lt;P&gt;Let’s take a concrete example: the class ProjectProgressTracker keeps track of a project progress – this is the Events Generator; when a task is added, completed or blocked (all internal states that the user doesn’t have access to), it needs to let a monitor system know – the Events Consumer. &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;// generates events when a task is added, completed, blocked etc
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ProjectProgressTracker &lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;static &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Random &lt;/SPAN&gt;r = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Random&lt;/SPAN&gt;((&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt;)&lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;.Now.Ticks);
    &lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Task&lt;/SPAN&gt;&amp;gt; tasks;

    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;ProjectProgressTracker(&lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;[] initialTasks) {
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.tasks = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Task&lt;/SPAN&gt;&amp;gt;();
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(initialTasks != &lt;SPAN style="COLOR: blue"&gt;null&lt;/SPAN&gt;)
            &lt;SPAN style="COLOR: blue"&gt;foreach &lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;s &lt;SPAN style="COLOR: blue"&gt;in &lt;/SPAN&gt;initialTasks)
                &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.tasks.Add(&lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Task&lt;/SPAN&gt;(s));
    }

    &lt;SPAN style="COLOR: blue"&gt;public void &lt;/SPAN&gt;NextAction() {
        &lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;randomNumber = r.Next(10);
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(randomNumber &amp;lt; 3)
            &lt;SPAN style="COLOR: green"&gt;// a new task was added
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;else if &lt;/SPAN&gt;(randomNumber &amp;gt; 6)
            &lt;SPAN style="COLOR: green"&gt;// a task is blocked
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;else
&lt;/SPAN&gt;            &lt;SPAN style="COLOR: green"&gt;// the task is done
&lt;/SPAN&gt;    }

    &lt;SPAN style="COLOR: blue"&gt;class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Task &lt;/SPAN&gt;{
        &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;name;
        &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;Task(&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;name)
            &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.name = name;
        &lt;SPAN style="COLOR: green"&gt;// other properties &amp;amp; methods
    &lt;/SPAN&gt;}
}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;This monitor system – StatusUpdatePublisher, sends mails and updates calendars. &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: green"&gt;// the class that reacts to events generated by ProjectProgressTracker
&lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;StatusUpdatePublisher &lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;public void &lt;/SPAN&gt;OnTaskAdded(&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;taskName) {
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.UpdateCalendar(&lt;SPAN style="COLOR: blue"&gt;true&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.SendMail(taskName, &lt;SPAN style="COLOR: #a31515"&gt;"added"&lt;/SPAN&gt;);
    }
    &lt;SPAN style="COLOR: blue"&gt;public void &lt;/SPAN&gt;OnTaskBlocked(&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;taskName) {
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.SendMail(taskName, &lt;SPAN style="COLOR: #a31515"&gt;"blocked"&lt;/SPAN&gt;);
    }
    &lt;SPAN style="COLOR: blue"&gt;public void &lt;/SPAN&gt;OnTaskCompleted(&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;taskName) {
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.UpdateCalendar(&lt;SPAN style="COLOR: blue"&gt;false&lt;/SPAN&gt;);
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.SendMail(taskName, &lt;SPAN style="COLOR: #a31515"&gt;"completed"&lt;/SPAN&gt;);
    }

    &lt;SPAN style="COLOR: blue"&gt;void &lt;/SPAN&gt;SendMail(&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;taskName, &lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;action) {
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.WriteLine(&lt;SPAN style="COLOR: #a31515"&gt;"Task {0} was {1}"&lt;/SPAN&gt;, taskName, action);
    }
    &lt;SPAN style="COLOR: blue"&gt;void &lt;/SPAN&gt;UpdateCalendar(&lt;SPAN style="COLOR: blue"&gt;bool &lt;/SPAN&gt;taskAdded) {
        &lt;SPAN style="COLOR: #2b91af"&gt;Console&lt;/SPAN&gt;.WriteLine(&lt;SPAN style="COLOR: #a31515"&gt;"Task was {0}"&lt;/SPAN&gt;, taskAdded ? &lt;SPAN style="COLOR: #a31515"&gt;"added" &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #a31515"&gt;"removed"&lt;/SPAN&gt;);
    }
}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;The 2 functionalities (generator / consumer) are completely separate. &lt;/P&gt;
&lt;P&gt;1. One way to implement this is to pass an Events Consumer object when constructing the Events Generator; then the generator class simply uses the consumer instance to call the desired methods. &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ProjectProgressTracker &lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;static &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Random &lt;/SPAN&gt;r = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;Random&lt;/SPAN&gt;((&lt;SPAN style="COLOR: blue"&gt;int&lt;/SPAN&gt;)&lt;SPAN style="COLOR: #2b91af"&gt;DateTime&lt;/SPAN&gt;.Now.Ticks);
    &lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;Task&lt;/SPAN&gt;&amp;gt; tasks;
    &lt;SPAN style="COLOR: blue"&gt;readonly &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;StatusUpdatePublisher &lt;/SPAN&gt;publisher;

    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;ProjectProgressTracker(
        &lt;SPAN style="COLOR: blue"&gt;string&lt;/SPAN&gt;[] initialTasks, &lt;SPAN style="COLOR: #2b91af"&gt;StatusUpdatePublisher &lt;/SPAN&gt;publisher) {
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.publisher = publisher;
        &lt;SPAN style="COLOR: green"&gt;// other functionality, see above
    &lt;/SPAN&gt;}

    &lt;SPAN style="COLOR: blue"&gt;public void &lt;/SPAN&gt;NextAction() {
        &lt;SPAN style="COLOR: green"&gt;// This should be replaced with the actual logic
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;randomNumber = r.Next(10);
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(randomNumber &amp;lt; 3)
            publisher.OnTaskAdded(randomNumber.ToString());
        &lt;SPAN style="COLOR: blue"&gt;else if &lt;/SPAN&gt;(randomNumber &amp;gt; 6)
            publisher.OnTaskBlocked(randomNumber.ToString());
        &lt;SPAN style="COLOR: blue"&gt;else
            &lt;/SPAN&gt;publisher.OnTaskCompleted(randomNumber.ToString());
    }

    &lt;SPAN style="COLOR: green"&gt;// other methods &amp;amp; classes
&lt;/SPAN&gt;}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;This works, but makes the events generator class &lt;STRONG&gt;tightly coupled&lt;/STRONG&gt; with the events consumer. Consider now that we want to add another monitor system that generates documentation tasks. If we follow the style above, we should pass it too inside the events generator class so it can call the correct methods. Of course, this model doesn’t scale very well. &lt;/P&gt;
&lt;P&gt;2. Another option is to raise some events at the correct time. &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskEventArgs &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;EventArgs &lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;TaskEventArgs(&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;taskName) {
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.TaskName = taskName;
    }
    &lt;SPAN style="COLOR: blue"&gt;public string &lt;/SPAN&gt;TaskName { &lt;SPAN style="COLOR: blue"&gt;get&lt;/SPAN&gt;; &lt;SPAN style="COLOR: blue"&gt;private set&lt;/SPAN&gt;; }
}

&lt;SPAN style="COLOR: blue"&gt;delegate void &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskEventHandler&lt;/SPAN&gt;(&lt;SPAN style="COLOR: blue"&gt;object &lt;/SPAN&gt;sender, &lt;SPAN style="COLOR: #2b91af"&gt;TaskEventArgs &lt;/SPAN&gt;e);&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;The events generator class has 3 events – for tasks added, completed and blocked. &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ProjectProgressTracker &lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;public event &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskEventHandler &lt;/SPAN&gt;OnTaskAdded;
    &lt;SPAN style="COLOR: blue"&gt;public event &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskEventHandler &lt;/SPAN&gt;OnTaskCompleted;
    &lt;SPAN style="COLOR: blue"&gt;public event &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskEventHandler &lt;/SPAN&gt;OnTaskBlocked;

    &lt;SPAN style="COLOR: blue"&gt;public void &lt;/SPAN&gt;NextAction() {
        &lt;SPAN style="COLOR: green"&gt;// This should be replaced with the actual logic
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;randomNumber = r.Next(10);
        &lt;SPAN style="COLOR: #2b91af"&gt;TaskEventArgs &lt;/SPAN&gt;eventArgs = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskEventArgs&lt;/SPAN&gt;(
            randomNumber.ToString());
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(randomNumber &amp;lt; 3)
            &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.OnTaskAdded(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;, eventArgs);
        &lt;SPAN style="COLOR: blue"&gt;else if &lt;/SPAN&gt;(randomNumber &amp;gt; 6)
            &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.OnTaskBlocked(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;, eventArgs);
        &lt;SPAN style="COLOR: blue"&gt;else
            this&lt;/SPAN&gt;.OnTaskCompleted(&lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;, eventArgs);
    }

    &lt;SPAN style="COLOR: green"&gt;// other methods &amp;amp; classes
&lt;/SPAN&gt;}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;Then the user of the class needs to hook up the events to the correct methods in the consumer class.&lt;/P&gt;&lt;PRE class=code&gt;ProjectProgressTracker tracker = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;ProjectProgressTracker(
    &lt;SPAN style="COLOR: blue"&gt;new string&lt;/SPAN&gt;[] {&lt;SPAN style="COLOR: #a31515"&gt;"Gather requirements"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"Prototype"&lt;/SPAN&gt;});
tracker.OnTaskAdded += 
    (&lt;SPAN style="COLOR: blue"&gt;object &lt;/SPAN&gt;o, TaskEventArgs e) =&amp;gt; publisher.OnTaskAdded(e.TaskName);
tracker.OnTaskCompleted += 
    (&lt;SPAN style="COLOR: blue"&gt;object &lt;/SPAN&gt;o, TaskEventArgs e) =&amp;gt; publisher.OnTaskCompleted(e.TaskName);
tracker.OnTaskBlocked += 
    (&lt;SPAN style="COLOR: blue"&gt;object &lt;/SPAN&gt;o, TaskEventArgs e) =&amp;gt; publisher.OnTaskBlocked(e.TaskName); 
&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;The benefit of this approach is that the generator class is not modified, no matter how many consumer classes we want to add to it. The disadvantage is that the user class needs to hook up all events to the correct implementation in consumers.&lt;/P&gt;
&lt;P&gt;3. Another solution is to use the Observable/Observer pattern. &lt;A href="http://www.exciton.cs.rice.edu/JavaResources/DesignPatterns/ObserverObservable.htm" mce_href="http://www.exciton.cs.rice.edu/JavaResources/DesignPatterns/ObserverObservable.htm"&gt;The Observer-Observable design pattern&lt;/A&gt; is a a very useful pattern for maintaining one-way communication between one object and a set of other objects. The observers receive communications from the Observable. Observers do not have a reference back to the Observable, so the communication is strictly from the Observable to the Observers. The observable is the object the Observers are "watching". The Observable maintains some sort of&amp;nbsp; list of references to Observers. That way, the Observable can send a message to all the Observers by calling each of their update methods. &lt;/P&gt;
&lt;P&gt;This is a known pattern, but since it’s not implemented in .Net Framework 3.5, I am just going to define some interfaces that suit my needs.&lt;/P&gt;
&lt;P&gt;Here, the class that generates events is the IObservable&amp;lt;T&amp;gt; and the class that consumes events in IObserver&amp;lt;T&amp;gt;:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;interface &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IObservable&lt;/SPAN&gt;&amp;lt;T&amp;gt; {
    &lt;SPAN style="COLOR: blue"&gt;void &lt;/SPAN&gt;Subscribe(&lt;SPAN style="COLOR: #2b91af"&gt;IObserver&lt;/SPAN&gt;&amp;lt;T&amp;gt; observer);
    &lt;SPAN style="COLOR: blue"&gt;bool &lt;/SPAN&gt;Unsubscribe(&lt;SPAN style="COLOR: #2b91af"&gt;IObserver&lt;/SPAN&gt;&amp;lt;T&amp;gt; observer);
}

&lt;SPAN style="COLOR: blue"&gt;interface &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IObserver&lt;/SPAN&gt;&amp;lt;T&amp;gt; {
    &lt;SPAN style="COLOR: blue"&gt;void &lt;/SPAN&gt;OnNext(T value);
}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;In our case, T is a class that contains the state of the task – the name of the task and the action that was taken:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;enum &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskAction &lt;/SPAN&gt;{ Added, Completed, Blocked }
&lt;SPAN style="COLOR: blue"&gt;class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskState &lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;TaskState(&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;taskName, &lt;SPAN style="COLOR: #2b91af"&gt;TaskAction &lt;/SPAN&gt;taskAction) {
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.TaskAction = taskAction;
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.TaskName = taskName;
    }
    &lt;SPAN style="COLOR: blue"&gt;public string &lt;/SPAN&gt;TaskName { &lt;SPAN style="COLOR: blue"&gt;get&lt;/SPAN&gt;; &lt;SPAN style="COLOR: blue"&gt;private set&lt;/SPAN&gt;; }
    &lt;SPAN style="COLOR: blue"&gt;public &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskAction &lt;/SPAN&gt;TaskAction { &lt;SPAN style="COLOR: blue"&gt;get&lt;/SPAN&gt;; &lt;SPAN style="COLOR: blue"&gt;private set&lt;/SPAN&gt;; }
}&lt;/PRE&gt;
&lt;P&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;So our classes change accordingly: the ProjectProgressTracker implements the IObservable interface, and the status update class implements the IObserver interface.&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ProjectProgressTracker &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;IObservable&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskState&lt;/SPAN&gt;&amp;gt; {
    &lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;IObserver&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskState&lt;/SPAN&gt;&amp;gt;&amp;gt; observers = 
        &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;IObserver&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskState&lt;/SPAN&gt;&amp;gt;&amp;gt;();

    &lt;SPAN style="COLOR: blue"&gt;public void &lt;/SPAN&gt;Subscribe(&lt;SPAN style="COLOR: #2b91af"&gt;IObserver&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskState&lt;/SPAN&gt;&amp;gt; observer) {
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.observers.Add(observer);
    }
    &lt;SPAN style="COLOR: blue"&gt;public bool &lt;/SPAN&gt;Unsubscribe(&lt;SPAN style="COLOR: #2b91af"&gt;IObserver&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskState&lt;/SPAN&gt;&amp;gt; observer) {
        &lt;SPAN style="COLOR: blue"&gt;return this&lt;/SPAN&gt;.observers.Remove(observer);
    }

    &lt;SPAN style="COLOR: blue"&gt;public void &lt;/SPAN&gt;NextAction() {
        &lt;SPAN style="COLOR: green"&gt;// This should be replaced with the actual logic
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;randomNumber = r.Next(10);
        &lt;SPAN style="COLOR: #2b91af"&gt;TaskEventArgs &lt;/SPAN&gt;eventArgs = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskEventArgs&lt;/SPAN&gt;(
            randomNumber.ToString());
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(randomNumber &amp;lt; 3)
            &lt;SPAN style="COLOR: blue"&gt;foreach &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;IObserver&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskState&lt;/SPAN&gt;&amp;gt; observer &lt;SPAN style="COLOR: blue"&gt;in this&lt;/SPAN&gt;.observers)
                observer.OnNext(
                    &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskState&lt;/SPAN&gt;(randomNumber.ToString(), &lt;SPAN style="COLOR: #2b91af"&gt;TaskAction&lt;/SPAN&gt;.Added));
        &lt;SPAN style="COLOR: blue"&gt;else if &lt;/SPAN&gt;(randomNumber &amp;gt; 6)
            &lt;SPAN style="COLOR: blue"&gt;foreach &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;IObserver&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskState&lt;/SPAN&gt;&amp;gt; observer &lt;SPAN style="COLOR: blue"&gt;in this&lt;/SPAN&gt;.observers)
                observer.OnNext(
                    &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskState&lt;/SPAN&gt;(randomNumber.ToString(), &lt;SPAN style="COLOR: #2b91af"&gt;TaskAction&lt;/SPAN&gt;.Blocked));
        &lt;SPAN style="COLOR: blue"&gt;else
            foreach &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;IObserver&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskState&lt;/SPAN&gt;&amp;gt; observer &lt;SPAN style="COLOR: blue"&gt;in this&lt;/SPAN&gt;.observers)
                observer.OnNext(
                    &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskState&lt;/SPAN&gt;(randomNumber.ToString(), &lt;SPAN style="COLOR: #2b91af"&gt;TaskAction&lt;/SPAN&gt;.Completed));
    }

    &lt;SPAN style="COLOR: green"&gt;// other methods &amp;amp; classes
&lt;/SPAN&gt;}

&lt;SPAN style="COLOR: blue"&gt;class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;StatusUpdatePublisher &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;IObserver&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskState&lt;/SPAN&gt;&amp;gt; {
    &lt;SPAN style="COLOR: blue"&gt;public void &lt;/SPAN&gt;OnNext(&lt;SPAN style="COLOR: #2b91af"&gt;TaskState &lt;/SPAN&gt;state) {
        &lt;SPAN style="COLOR: blue"&gt;switch &lt;/SPAN&gt;(state.TaskAction) {
            &lt;SPAN style="COLOR: blue"&gt;case &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskAction&lt;/SPAN&gt;.Added:
                &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.OnTaskAdded(state.TaskName); &lt;SPAN style="COLOR: blue"&gt;break&lt;/SPAN&gt;;
            &lt;SPAN style="COLOR: blue"&gt;case &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskAction&lt;/SPAN&gt;.Blocked:
                &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.OnTaskBlocked(state.TaskName); &lt;SPAN style="COLOR: blue"&gt;break&lt;/SPAN&gt;;
            &lt;SPAN style="COLOR: blue"&gt;case &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskAction&lt;/SPAN&gt;.Completed:
                &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.OnTaskCompleted(state.TaskName); &lt;SPAN style="COLOR: blue"&gt;break&lt;/SPAN&gt;;
        }
    }

    &lt;SPAN style="COLOR: green"&gt;// the other methods
&lt;/SPAN&gt;}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;PRE class=code&gt;&lt;/PRE&gt;
&lt;P&gt;Now the user just constructs the classes and registers the desired consumers:&lt;/P&gt;&lt;PRE class=code&gt;StatusUpdatePublisher publisher = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;StatusUpdatePublisher();
ProjectProgressTracker tracker = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;ProjectProgressTracker(
    &lt;SPAN style="COLOR: blue"&gt;new string&lt;/SPAN&gt;[] {&lt;SPAN style="COLOR: #a31515"&gt;"Gather requirements"&lt;/SPAN&gt;, &lt;SPAN style="COLOR: #a31515"&gt;"Prototype"&lt;/SPAN&gt;});
tracker.Subscribe(publisher);
&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;This pattern has a couple of advantages: &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Multiple consumers can be added easily 
&lt;LI&gt;The events generator doesn’t need to know anything about the consumers; no change in the generator is needed when one or more of the consumers is changed.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;But we pay the penalty of wrapping the state in a class and then analyzing it in the Observer to see what concrete method to implement. &lt;/P&gt;
&lt;P&gt;4. Another possible implementation is the IRegistrar pattern (Disclaimer: I’m not aware of a pattern with this name described. The name is something I came up with). This is somewhat similar with the IObservable pattern, but instead of a class that wraps the state when the event occurs, we specify an interface for the type of events. &lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;interface &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IProjectEvents &lt;/SPAN&gt;{
    &lt;SPAN style="COLOR: blue"&gt;void &lt;/SPAN&gt;OnTaskAdded(&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;taskName);
    &lt;SPAN style="COLOR: blue"&gt;void &lt;/SPAN&gt;OnTaskBlocked(&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;taskName);
    &lt;SPAN style="COLOR: blue"&gt;void &lt;/SPAN&gt;OnTaskCompleted(&lt;SPAN style="COLOR: blue"&gt;string &lt;/SPAN&gt;taskName);
}

&lt;SPAN style="COLOR: blue"&gt;interface &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;IRegistrar&lt;/SPAN&gt;&amp;lt;T&amp;gt; {
    &lt;SPAN style="COLOR: blue"&gt;void &lt;/SPAN&gt;Subscribe(T consumer);
    &lt;SPAN style="COLOR: blue"&gt;bool &lt;/SPAN&gt;Unsubscribe(T consumer);
}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;The events consumers implement this interface:&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;StatusUpdatePublisher &lt;/SPAN&gt;: IProjectEvents {
    &lt;SPAN style="COLOR: green"&gt;// the original methods
&lt;/SPAN&gt;}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;The generator class can register consumers that know to consume events of type T (IProjectEvents in our case).&lt;/P&gt;&lt;PRE class=code&gt;&lt;SPAN style="COLOR: blue"&gt;class &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;ProjectProgressTracker &lt;/SPAN&gt;: &lt;SPAN style="COLOR: #2b91af"&gt;IRegistrar&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;IProjectEvents&lt;/SPAN&gt;&amp;gt; {
    &lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;IProjectEvents&lt;/SPAN&gt;&amp;gt; consumers = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;List&lt;/SPAN&gt;&amp;lt;&lt;SPAN style="COLOR: #2b91af"&gt;IProjectEvents&lt;/SPAN&gt;&amp;gt;();

    &lt;SPAN style="COLOR: blue"&gt;public void &lt;/SPAN&gt;Subscribe(&lt;SPAN style="COLOR: #2b91af"&gt;IProjectEvents &lt;/SPAN&gt;consumer) {
        &lt;SPAN style="COLOR: blue"&gt;this&lt;/SPAN&gt;.consumers.Add(consumer);
    }
    &lt;SPAN style="COLOR: blue"&gt;public bool &lt;/SPAN&gt;Unsubscribe(&lt;SPAN style="COLOR: #2b91af"&gt;IProjectEvents &lt;/SPAN&gt;consumer) {
        &lt;SPAN style="COLOR: blue"&gt;return this&lt;/SPAN&gt;.consumers.Remove(consumer);
    }

    &lt;SPAN style="COLOR: blue"&gt;public void &lt;/SPAN&gt;NextAction() {
        &lt;SPAN style="COLOR: green"&gt;// This should be replaced with the actual logic
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: blue"&gt;int &lt;/SPAN&gt;randomNumber = r.Next(10);
        &lt;SPAN style="COLOR: #2b91af"&gt;TaskEventArgs &lt;/SPAN&gt;eventArgs = &lt;SPAN style="COLOR: blue"&gt;new &lt;/SPAN&gt;&lt;SPAN style="COLOR: #2b91af"&gt;TaskEventArgs&lt;/SPAN&gt;(
            randomNumber.ToString());
        &lt;SPAN style="COLOR: blue"&gt;if &lt;/SPAN&gt;(randomNumber &amp;lt; 3)
            &lt;SPAN style="COLOR: blue"&gt;foreach &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;IProjectEvents &lt;/SPAN&gt;consumer &lt;SPAN style="COLOR: blue"&gt;in this&lt;/SPAN&gt;.consumers)
                consumer.OnTaskAdded(randomNumber.ToString());
        &lt;SPAN style="COLOR: blue"&gt;else if &lt;/SPAN&gt;(randomNumber &amp;gt; 6)
            &lt;SPAN style="COLOR: blue"&gt;foreach &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;IProjectEvents &lt;/SPAN&gt;consumer &lt;SPAN style="COLOR: blue"&gt;in this&lt;/SPAN&gt;.consumers)
                consumer.OnTaskBlocked(randomNumber.ToString());
        &lt;SPAN style="COLOR: blue"&gt;else
            foreach &lt;/SPAN&gt;(&lt;SPAN style="COLOR: #2b91af"&gt;IProjectEvents &lt;/SPAN&gt;consumer &lt;SPAN style="COLOR: blue"&gt;in this&lt;/SPAN&gt;.consumers)
                consumer.OnTaskCompleted(randomNumber.ToString());
    }

    &lt;SPAN style="COLOR: green"&gt;// other methods &amp;amp; classes
&lt;/SPAN&gt;}&lt;/PRE&gt;&lt;A href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;&lt;A href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/A&gt;
&lt;P&gt;The usage is just as the one for the IObservable pattern. &lt;/P&gt;
&lt;P&gt;In our case, it seems that this pattern works the best, because we get all the previous advantages plus strongly typing when calling consumer methods. &lt;/P&gt;
&lt;P&gt;Depending on your project requirements, you may choose one of these solutions or look for a better one. Some requirements may be:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Loosely coupling between the events generator and the consumers 
&lt;UL&gt;
&lt;LI&gt;Changing the consumer doesn’t affect the generator&lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;One or more consumers can be added 
&lt;LI&gt;Producers can have inner producers and the consumers must be propagated 
&lt;LI&gt;Etc… who knows?&lt;/LI&gt;&lt;/UL&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9815496" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/oanapl/archive/tags/Design+patterns/default.aspx">Design patterns</category></item></channel></rss>