Friday, November 16, 2012

Observer Design Pattern using Delegates/events

Today I want to discuss with you how to implement Observer design pattern using delegate and event in asp.net /c#.

Observer Pattern

The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. It is mainly used to implement distributed event handling systems. The Observer pattern is also a key part in the familiar Model View Controller (MVC) architectural pattern.(wikipedia).

UML class diagram of Observer pattern(wikipedia)





The Observer Pattern describes the dependence relationship between one object (observable) to many objects (observers). It's also called Model/View, Dependents, or Distributor/Listener pattern.This article introduces an implementation when we can use the Observer pattern to keep all observer objects updated after things have changed.

Case project

In this case, patient is an ObservableObject that needs to send out the notification when the hospital updates his/her physical status. The hospital will determine who will be notified when the patient status is updated.


In our scenario,  patient (observable object) admitted in hospital and they are observed by multiple observer (relative and doctor). Each observer get multiple time physical updated status from hospital daily.


Sample Class diagram for our case project

Code:
IObservable.cs


namespace ObserverDesignPatternLib
{
    public delegate void NotifyObserver(string key);
    internal interface IObservable
    {
        void AddObserver(NotifyObserver ob);
        void RemoveObserver(NotifyObserver ob);
        void Notify(string observerName);
    }
}
----------------------------------------------
ObservableObject.cs


namespace ObserverDesignPatternLib
{
    public class ObservableObject:IObservable
    {
        public event NotifyObserver NotifyObserverEvent;

        public void AddObserver(NotifyObserver ob)
        {
            NotifyObserverEvent += ob;
        }

        public void RemoveObserver(NotifyObserver ob)
        {
            NotifyObserverEvent -= ob;
        }

        public void Notify(string observerName)
        {
            if (NotifyObserverEvent != null)
            {
                NotifyObserverEvent(observerName);
            }
        }
    }
}


-----------------------------------------------

Status.cs

public class Status
    {
        public string Description { get; set; }
        public DateTime UpdatedOn { get; set; }

        public Status(string notes)
        {
            Description = notes;
            UpdatedOn = DateTime.Now;
        }
    }
----------------------------------------

Patient .cs

public class Patient : ObservableObject
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public string Address { get; set; }

        private Status _patientStatus;

        public Status PatientStatus
        {
            get { return _patientStatus; }
            set
            {
                _patientStatus = value;
                Notify(this.Name);
            }
        }
    }
----------------------------------------

Doctor.cs 

public class Doctor
    {
        private Dictionary _patients = new Dictionary();

        public Dictionary Patients
        {
            get { return _patients; }
            set { _patients = value; }
        }


        public void RecivePatientStatus(string paitientName)
        {
            Console.WriteLine("Doctor received {0}'s new status:\nAge: {1}\nAddress:{2}\nUpdates on: {3}\nDescription: {4} \n\n",
                Patients[paitientName].Name,
                Patients[paitientName].Age,
                Patients[paitientName].Address,
                Patients[paitientName].PatientStatus.UpdatedOn,
                Patients[paitientName].PatientStatus.Description);
        }
    }
---------------------------------------------

Relative.cs

public class Relative
    {
        private Dictionary _patients = new Dictionary();

        public Dictionary Patients
        {
            get { return _patients; }
            set { _patients = value; }
        }

        public void PatientStatusUpdate(string key)
        {
            Console.WriteLine("Relative received {0}'s new status:\nAge: {1}\nAddress:{2}\nUpdates on: {3}\nDescription: {4} \n\n",
                Patients[key].Name,
                Patients[key].Age,
                Patients[key].Address,
                Patients[key].PatientStatus.UpdatedOn,
                Patients[key].PatientStatus.Description);
        }
    }
------------------------------------------------
Progarm.cs



class Program
    {
        static void Main(string[] args)
        {
            //Two Patients been created
            var patientFever = new Patient();
            var patientDiarhoea = new Patient();

            patientFever.Name = "Al Amin";
            patientFever.Age = 15;
            patientFever.Address = "Gulshan,Dhaka";
         
            patientDiarhoea.Name = "Abdul Gaffar";
            patientDiarhoea.Age = 22;
            patientDiarhoea.Address = "Mehedibag,Chittagong.";

            //Relative object created for each patient
            var relativeFever = new Relative();
            relativeFever.Patients.Add(patientFever.Name, patientFever);

            var relativeDiarhoea = new Relative();
            relativeDiarhoea.Patients.Add(patientDiarhoea.Name, patientDiarhoea);

            //one doctor object created
            //this doctor is hospital's duty doctor, he is notified patient status time to time
            var doctor = new Doctor();
            doctor.Patients.Add(patientFever.Name, patientFever);
            doctor.Patients.Add(patientDiarhoea.Name, patientDiarhoea);


            //hospital also send status to the relatives.
            patientFever.AddObserver(new NotifyObserver(relativeFever.PatientStatusUpdate));
            patientDiarhoea.AddObserver(new NotifyObserver(relativeDiarhoea.PatientStatusUpdate));

            //Update status for both Patients. relatives will receive the status at the same time
            patientFever.PatientStatus = new Status(String.Format("{0} is feeling bed.", patientFever.Name));
            patientDiarhoea.PatientStatus = new Status(String.Format("{0} is ", patientDiarhoea.Name));

            //Updates the status after 2 secs
            Thread.Sleep(2000);

            //after 5 secs, patientDiarhoea doesn't feel well. need to get doctor involved
            patientFever.AddObserver(new NotifyObserver(doctor.RecivePatientStatus));
            patientDiarhoea.AddObserver(new NotifyObserver(doctor.RecivePatientStatus));

            //update two Patients' status.
            //relatives will recive their Patients status
            //Doctor start reciving patient's status
            patientFever.PatientStatus = new Status(String.Format("{0} is feel out of sort. Temparature : 102 F", patientFever.Name));
            patientDiarhoea.PatientStatus = new Status(String.Format("{0} is sick due to in digest.", patientDiarhoea.Name));

            //Updates the status after 3 secs
            Thread.Sleep(3000);

            //update two Patients' status
            patientFever.PatientStatus = new Status(String.Format("{0} is not feel better. Still Temparature : 100 F", patientFever.Name));
            patientDiarhoea.PatientStatus = new Status(String.Format("{0} is back to normal but weak.", patientDiarhoea.Name));


            //Updates the status after 3 secs
            Thread.Sleep(3000);
                     
            //since patient is become better. hospital's unsubscribe the doctor's observation
            patientDiarhoea.RemoveObserver(new NotifyObserver(doctor.RecivePatientStatus));

            //update two Patients' status
            patientFever.PatientStatus = new Status(String.Format("{0} is now back to normal.", patientFever.Name));
            patientDiarhoea.PatientStatus = new Status(String.Format("{0} is recover weakness.", patientDiarhoea.Name));

            Console.WriteLine("Patients regular status report.");
            Console.Read();
        }
    }

Final output



5 comments:

Sudipto said...

Very easy to understand ..thanks..carry on

Vinay prashad said...

Superb article...I like it...

Khris said...

Clear and easy explanation.Thanks

Web development company Delhi said...

You have given very nice post it is very knowledgable and result oriented.

Website is very good tool for any company.

Anuj said...

This is very useful information shared here. I am really thankful for this. 99th.co.in64884 105

Method 'StartWorkflowOnListItem' in type 'Microsoft.SharePoint.WorkflowServices.FabricWorkflowInstanceProvider'

Exception: Method 'StartWorkflowOnListItem' in type 'Microsoft.SharePoint.WorkflowServices.FabricWorkflowInstanceProvider'...