none
Observer pattern dilemma... RRS feed

  • Question

  • Dear Freinds,
    I am in a dilemma after digging deep into the Observer Pattern,
    As per as knew untill now, We could implement the Observer using the Interfaces and Delegates/Events.
    I thought to check out delegated example and downloaded the code from the net and it was working just fine, then When I saw the code carefully I found that though it is working just fine now, Then I thought Lemme see by making the direct calls instead of the calls through the usage of the delegates and the events, It worked just fine now also, So I am pasting both the old code where it was done using the delegates and the events n the one which I have modified by giving the direct calls, So please can anybody tell me actually what is the purpose of the delegates and the events if the code could work without them also, I would be grateful to receive the reply on this.

    Before:

    http://www.codeproject.com/KB/dialog/ObserverPattern.aspx?display=Print

    After :

    Library.cs
    //////////////////Library.cs starts here
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Collections;
    using System.Windows.Forms;
    using System.Drawing;

    namespace EventAndDelegate
    {
        public class Observer
        {
            private delegate void ColorEventHandler(string _color);
            private event ColorEventHandler ColorChangedEvent;
            private TextBox txt;

            public Observer(TextBox _txt)
            {
                //this.ColorChangedEvent += new ColorEventHandler(Observer_ColorChangedEvent);
                //Observer_ColorChangedEvent("GREEN");
                this.txt = _txt;
            }

            private void OnChange(string _color)
            {
                //if (ColorChangedEvent != null)
                //{
                //    ColorChangedEvent(_color);
                //}
                Observer_ColorChangedEvent("GREEN");
            }

            public void Update(string _color)
            {
                OnChange(_color);
            }

            private void Observer_ColorChangedEvent(string _color)
            {
                if (txt == null)
                    return;
                switch (_color)
                {
                    case "RED":
                        txt.BackColor = Color.Red;
                        break;
                    case "BLUE":
                        txt.BackColor = Color.Blue;
                        break;
                    case "GREEN":
                        txt.BackColor = Color.Green;
                        break;
                    default:
                        txt.BackColor = Color.Gray;
                        break;
                }
            }
        }

        public class Subject
        {
            ArrayList arrObs = new ArrayList();

            //private delegate void ColorEventHandler(string _color);
            //private event ColorEventHandler ColorChangedEvent;

            private delegate void NotifyHandler(string _color);
            private event NotifyHandler NotifyEvent;

            public Subject()
            {
                this.NotifyEvent += new NotifyHandler(Notify);
            }

            public void UpdateClient(string _color)
            {
                //OnNotify(_color);
                Notify(_color);
            }

            private void OnNotify(string _color)
            {
                //if (NotifyEvent != null)
                //{
                    //NotifyEvent(_color);
                    Notify(_color);
                //}
            }

            private void Notify(string _color)
            {
                for (int i = 0; i < arrObs.Count; i++)
                {
                    Observer obs = (Observer)arrObs[i];
                    obs.Update(_color);
                }
            }

            public void RegisterClient(Observer obs)
            {
                arrObs.Add(obs);
            }
        }
    }

    //////////////////Library.cs ends here
    Thursday, June 4, 2009 10:15 AM

Answers

  • Why you should prefer events to hardcoding the Observer pattern:

    1. Encapsulation - Implementing observer pattern the long way forces the observer's update to be somehow accessible to the subject via the accessibility modifier.  This means it has to be public or internal.  Events don't carry this requirement.
    2. Flexibility - Hardcoding the observer pattern means that the observer's update method must have a specific name.  This means you can't have more than one implementation per object.  There may come a point when you want to subscribe one method under one circumstance and another method under another circumstance.  Events provide this flexibility.
    3. Subscribing to multiple objects - Stretching your implementation to subscribe to more than one type of object is going to be difficult.  It's going to require you to create a different interface for each and every subject your observer wishes to subscribe to, unless the multiple objects are of the same type.  Events don't carry this requirement.
    4. OO inheritance is simpler -  The requirement to inherit from "Observer" can be very limiting.  Especially considering that "Observer" in your situation is a class, this is going to prevent more useful inheritance structures. 
    5. Easier to maintain - Events take far less code in the long run, and are easier to maintain. You don't need to implement "RegisterClient" methods for events to work, and your subject can feel free to have several different methods it can subscribe to.

    That being said, one advantage of observer pattern is it's ability to work with SQL CLR, which currently doesn't support objects that carry events. 


    David Morton - http://blog.davemorton.net/ - @davidmmorton
    Thursday, June 4, 2009 1:19 PM

All replies

  • Why you should prefer events to hardcoding the Observer pattern:

    1. Encapsulation - Implementing observer pattern the long way forces the observer's update to be somehow accessible to the subject via the accessibility modifier.  This means it has to be public or internal.  Events don't carry this requirement.
    2. Flexibility - Hardcoding the observer pattern means that the observer's update method must have a specific name.  This means you can't have more than one implementation per object.  There may come a point when you want to subscribe one method under one circumstance and another method under another circumstance.  Events provide this flexibility.
    3. Subscribing to multiple objects - Stretching your implementation to subscribe to more than one type of object is going to be difficult.  It's going to require you to create a different interface for each and every subject your observer wishes to subscribe to, unless the multiple objects are of the same type.  Events don't carry this requirement.
    4. OO inheritance is simpler -  The requirement to inherit from "Observer" can be very limiting.  Especially considering that "Observer" in your situation is a class, this is going to prevent more useful inheritance structures. 
    5. Easier to maintain - Events take far less code in the long run, and are easier to maintain. You don't need to implement "RegisterClient" methods for events to work, and your subject can feel free to have several different methods it can subscribe to.

    That being said, one advantage of observer pattern is it's ability to work with SQL CLR, which currently doesn't support objects that carry events. 


    David Morton - http://blog.davemorton.net/ - @davidmmorton
    Thursday, June 4, 2009 1:19 PM
  • Hi Davi,
    First Thing is First, Thank you very much for the lightning fast response, I was not expecting this quick response, When I was writting this query for this post, I had only one strong point to think in the favour of delegates i.e. flexibility and the manageability, But I was not sure, n wanted some light to be thrown on my thought n also I was looking for some expert advice who have already tamed some bully Patterns, Because though I am an experienced developer, I am not much exposed to designing so your clear explanation cleared my doubt, So I am marking this as Answered, Once again Thank You Very Much.
    Thursday, June 4, 2009 5:08 PM