Click here to Skip to main content
Licence CPOL
First Posted 13 Jul 2009
Views 20,297
Downloads 83
Bookmarked 30 times

Observer Design Pattern in C#

By Salmanzz | 13 Jul 2009 | Technical Blog
Observer Design Pattern in C#
2 votes, 50.0%
1

2
1 vote, 25.0%
3

4
1 vote, 25.0%
5
2.50/5 - 4 votes
μ 2.50, σa 3.35 [?]

Introduction

The Observer design pattern is a relationship between objects so that when one changes its state, all the others are notified accordingly. In other words, it defines that an object must be able to notify other objects without making assumptions about what these objects are.

Observer design pattern is quite useful when a change to one object requires changing others but, you don't know how many objects need to be changed.

Using Observer Design Pattern in Blog Subscriber Example

In this example, I have used two other behavioral patterns which are Iterator Design Pattern in C# and Facade Design Pattern in C#. The simplest way to understand observer pattern is to look at blogs, which are websites where people write about different topics. Take an example of one blog where so many users have subscribed themselves for any new post. As we all know, bloggers don't always post regularly so it would be great for bloggers to alert all subscribers whenever the blogger posts a new topic.

  • Blog is a class which deals with the new blog post and also with the blog subscribers.
  • BlogPost is a class which deals with the posting of a new article.
  • Subscribers are the users who have subscribed themselves for alerts of new articles.
  • Facade deals them in a simpler way and gives you operations like PublishSinglePost() or PublishMultiPost(), etc.
  • Subject class whose instances independently change their state and it notifies to all the subscribers.
  • Run method loops through all of the Subscribers calling their Update methods to notify them about post. It also contains methods for attaching and detaching functions with event.

Imagine using Iterator Design Pattern in C# we have a list of subscribers as follows:

class Subscriber
    {
        public string Name { get; set; }
        public string Email { get; set; }
        public Subscriber(string name, string email)
        {
            this.Name = name;
            this.Email = email;
        }
    }

    class BlogSubscribers : IEnumerable
    {
        Subscriber[] Arrays = { new Subscriber("user1", firstEmail@gmail.com), 
				new Subscriber("user2", "2ndEmail@gmail.com") };

        public IEnumerator GetEnumerator()
        {
            foreach (Subscriber element in Arrays)
                yield return element;
        }
    } 

For more details related to the above code and Iterator design pattern, read my article on Iterator Design Pattern in C#.

Subject class instances independently change their state and it notifies to all the subscribers. It defines a Dictionary object to store the subscribers name and their callback functions.

public delegate void Callback(String subscriber);
    class Subject
    {
        //Declaring delegate 
        Dictionary<string, Callback> Notify = new Dictionary<string, Callback>();
        //Declaring Event 
        // List of Users as IEnumerable
        BlogSubscribers blogSubscribers = new BlogSubscribers();

        /// <summary>
        /// Attaching the events
        /// </summary>
        /// <param name="subscriber">its the name of user or email address</param>
        /// <param name="Update">A method to attach </param>
        public void Attach(string subscriber, Callback Update)
        {
            if (!Notify.ContainsKey(subscriber))
            {
                Notify[subscriber] = delegate { };
            }

            Notify[subscriber] += Update;
        }
        /// <summary>
        /// To Detach method for specific user
        /// </summary>
        /// <param name="subscriber">its the name of user or email address</param>
        /// <param name="Update">A method to attach</param>
        public void Detach(string subscriber, Callback Update)
        {

            Notify[subscriber] -= Update;
        }
        /// <summary>
        /// Loop through all users to notify for anychange
        /// </summary>
        public void Run()
        {
            foreach (Subscriber subscriber in blogSubscribers)
            {
                string message = string.Format(" To {0}<{1}> ", 
				subscriber.Name, subscriber.Email);
                Notify[subscriber.Name](message);
            }
        }
    }

An interface for IObserver specifies how they should be updated. A BlogSpot for posting new articles and observers as a BlogObserver:

interface IObserver
    {
        void Update(string message);
    }
    class BlogPost
    {
        public string PostName { get; set; }

    }
    class BlogObserver : IObserver
    {
        //name of the posting

        // Implementing through IOC Inversion of control 
        Subject subject;
        List<BlogPost> ListOfBlogNewPosts = new List<BlogPost>();
        public BlogObserver(Subject subject)
        {
            this.subject = subject;
            subject.Attach("user1", Update);
            subject.Attach("user2", Update);

        }
        public void AddPost(BlogPost blogPost)
        {
            ListOfBlogNewPosts.Add(blogPost);
        }

        public void Update(string message)
        {
            foreach (BlogPost blogPost in ListOfBlogNewPosts)
            {
                Console.WriteLine
		("--------------------- New Posting ---------------------");
                Console.WriteLine(" {0} for Post {1}", message, blogPost.PostName);
                Console.WriteLine();
            }
        }
        public void DetachFromPost(string subscriber)
        {
            subject.Detach(subscriber, Update);
        }
    }

I have used Facade Design Pattern in C# to make an easy interface for these different sub systems.

 public class BlogFacade
    {
        public static void PublishMultiPost()
        {
            Subject subject = new Subject();
            BlogPost Ps3 = new BlogPost();
            Ps3.PostName = "PS3";
            BlogPost Xbox = new BlogPost();
            Xbox.PostName = "Xbox";
            BlogObserver salmanBlog = new BlogObserver(subject);
            salmanBlog.AddPost(Ps3);
            salmanBlog.AddPost(Xbox);
            //let's try to detach users2 from the subscriber list for posting xbox
            //salmanBlog.DetachFromPost("user2");
            subject.Run();
        }
        public static void PublishSinglePost()
        {
            Subject subject = new Subject();
            BlogPost Xbox = new BlogPost();
            Xbox.PostName = "Xbox";
            BlogObserver salmanBlog = new BlogObserver(subject);
            salmanBlog.AddPost(Xbox);
            subject.Run();
        }
    } 

For more details regarding facade pattern, visit Facade Design Pattern in C#.

static void Main()
    {
        //BlogFacade.PublishSinglePost();
        BlogFacade.PublishMultiPost();
    }  

Output

So if you run facade operation BlogFacade.PublishMultiPost(); by commenting //salmanBlog.DetachFromPost("user2"); then output will be:

image1.png

and if you uncomment this salmanBlog.DetachFromPost("user2"); and run BlogFacade.PublishMultiPost(); the output will be:

image2.png

because we have unsubscribed user2 from the list. So that is our blog on Observer pattern if for any new post or change in post, all the others are notified accordingly.

Your feedback is welcome.

View this article on my blog.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Salmanzz

Software Developer (Senior)
BMJ
United Kingdom United Kingdom

Member


Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralMy vote of 1 PinmemberJay R. Wren5:18 21 Jul '09  
GeneralRe: My vote of 1 PinmemberSalmanzz6:28 21 Jul '09  
GeneralMy vote of 1 PinmemberSteve Hansen21:29 13 Jul '09  
GeneralEvents PinmemberSteve Hansen4:45 13 Jul '09  
GeneralRe: Events PinmemberSalmanzz7:08 13 Jul '09  
GeneralRe: Events Pinmembersupercat914:40 13 Jul '09  
GeneralRe: Events PinmemberSteve Hansen21:25 13 Jul '09  
GeneralRe: Events [modified] PinmemberSalmanzz2:20 14 Jul '09  
GeneralRe: Events Pinmembersupercat97:29 14 Jul '09  
GeneralRe: Events PinmemberSteve Hansen7:57 14 Jul '09  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120209.1 | Last Updated 13 Jul 2009
Article Copyright 2009 by Salmanzz
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid