Click here to Skip to main content
Click here to Skip to main content

Observer Pattern

, 2 Dec 2009
Rate this:
Please Sign up or sign in to vote.
Observer pattern

Editorial Note

This articles was originally at wiki.asp.net but has now been given a new home on CodeProject. Editing rights for this article has been set at Bronze or above, so please go in and edit and update this article to keep it fresh and relevant.

Introduction

The observer design pattern defines a one to many dependency between an object and its dependents.
The dependency is created in order to inform the dependants that the object changed its state and therefore the dependants can react to the change.

A very good example of such behavior is the blogging systems were subscribers are notified whenever a blogger published a new post. Another real world example can be the MVC architecture pattern which uses the pattern.

Use Cases for the Observer Pattern

You should use the pattern in the following cases:

  • You have a publisher/subscriber model.
  • Objects need to be notified of a change in another objects.
  • You need that the object that notify its state change would not know about its subscribers.

Observer using .NET Built in Features

Check this really cool Patterns and Practices article Implementing Observer in .NET.

UML Diagram

Example in C#

The following code is an example of how to implement the pattern:

    #region Subject
    public abstract class Subject
    {
        #region Members
        private List<IObserver> _observers;
        #endregion

        #region Ctor
        /// <summary>
        /// Construct a new subject object
        /// </summary>
        public Subject()
        {
            _observers = new List<IObserver>();
        }
        #endregion

        #region Methods
        /// <summary>
        /// Attaches a new observer to the subject
        /// </summary>
        /// <param name="observer">The observer to attach</param>
        public void Attach(IObserver observer)
        {
            _observers.Add(observer);
        }

        /// <summary>
        /// Detaches an observer from the subject
        /// </summary>
        /// <param name="observer">The observer to detach</param>

        public void Detach(IObserver observer)
        {
            _observers.Remove(observer);
        }

        /// <summary>
        /// Notify all the observers about the change in the subject's state
        /// </summary>
        public void Notify()
        {
            foreach (IObserver observer in _observers)
            {
                observer.Update();
            }
        }
        #endregion
    }
    #endregion

    #region Concrete Subject
    public class ConcreteSubject<T> : Subject
    {
        #region Properties
        /// <summary>
        /// The state of the subject
        /// </summary>
        public T SubjectState { get; set; }
        #endregion
    }
    #endregion

    #region Observer
    public interface IObserver
    {
        void Update();
    }
    #endregion

    #region Concrete Observer
    public class ConcreteObserver<T> : IObserver
    {
        #region Properties
        /// <summary>
        /// The subject the observer holds
        /// </summary>
        public ConcreteSubject<T> Subject { get; set; }
        private T _observerState;
        #endregion

        #region Ctor
        /// <summary>
        /// Construct a new concrete observer with the given subject
        /// </summary>
        /// <param name="subject">The given subject</param>
        public ConcreteObserver(ConcreteSubject<T> subject)
        {
            Subject = subject;
        }
        #endregion

        #region IObserver Members
        /// <summary>
        /// Make an update to the observer state whenever the
        /// method is called
        /// </summary>
        public void Update()
        {
            _observerState = Subject.SubjectState;

            Console.WriteLine("The new state of the observer:{0}", _observerState.ToString());
        }
        #endregion
    }
    #endregion 

The example is simple to follow.
We have an IObserver interface and a Subject abstract class. The observers are registered in the subject with the Attach method and also can be detached. The subject implements the Notify method that notifies every observer when the subject state was changed.
When the state changes, the observer makes an update which is the main method of the IObserver interface.

The following code is an example scenario of how to run the pattern in console application:

   ConcreteSubject<string> subject = new ConcreteSubject<string>();

   subject.Attach(new ConcreteObserver<string>(subject));
   subject.Attach(new ConcreteObserver<string>(subject));
   subject.SubjectState = "Hello World";

   subject.Notify();

   Console.Read(); 

Summary

To sum up, the observer pattern is widely used and it is very helpful.
You can see the uses of the pattern in the MVC framework for example or in the Microsoft blogs when you subscribe to a blog in order to be notified of new blogger posts. The next post in the design patterns series will be the last pattern post and it will include the interpreter pattern.

License

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

About the Author

ASP.NET Community

United States United States
The ASP.NET Wiki was started by Scott Hanselman in February of 2008. The idea is that folks spend a lot of time trolling the blogs, googlinglive-searching for answers to common "How To" questions. There's piles of fantastic community-created and MSFT-created content out there, but if it's not found by a search engine and the right combination of keywords, it's often lost.
 
The ASP.NET Wiki articles moved to CodeProject in October 2013 and will live on, loved, protected and updated by the community.
Group type: Collaborative Group

247 members


Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web03 | 2.8.140721.1 | Last Updated 2 Dec 2009
Article Copyright 2008 by ASP.NET Community
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid