Tuesday, January 29, 2008

Chain of Responsibility

This pattern is part of a group of patterns that deals with communication between two or more different objects. This pattern allows us to provide loose coupling between objects and also encourages testable code. In Chain of Responsibility we will have a chain of command objects that are passed requests. As we go down the chain....those objects that can handle the request do so....those that can't pass the request down the chain.

Our command objects will adhere to the ICommand interface. Any of the command objects that are part of the chain will have the 'Run' and 'Successor' methods defined in the interface.I can use the Successor method to allow us to setup the chain or we can use the constructor that is defined in each one of the following classes. I have chosen to simply utilize the constructor for simplicity.




public interface ICommand
{
ICommand Successor { get; set;}
void Run(int request);
}


I am going to define three different classes that will implement the ICommand interface.




public class EmailLogger: ICommand
{
private ICommand successor;


public EmailLogger()
{
}

public EmailLogger(ICommand successor)
{
this.successor = successor;
}

public ICommand Successor
{
get { return successor; }
set { successor = value; }
}

public void Run(int request)
{

if (request==1)
Console.WriteLine("I am the Email Logger. I can handle one.");
else if (successor != null)
successor.Run(request);
}


}


public class StdErrLogger: ICommand
{
private ICommand successor;


public StdErrLogger()
{
}

public StdErrLogger(ICommand successor)
{
this.successor = successor;
}

public ICommand Successor
{
get { return successor; }
set { successor = value; }
}

public void Run(int request)
{

if (request==2)
Console.WriteLine("I am the STD Error Logger. I can handle two.");
else if (successor != null)
successor.Run(request);
}
}

public class StdOutLogger : ICommand
{
private ICommand successor;


public StdOutLogger()
{
}

public StdOutLogger(ICommand successor)
{
this.successor = successor;
}

public ICommand Successor
{
get { return successor; }
set { successor = value; }
}

public void Run(int request)
{
if (request==3)
Console.WriteLine("I am the STD Out Logger. I can handle three.");
else if (successor!=null)
successor.Run(request);
}
}


You will notice that the meat of the object for the chain to work according to the pattern is each of the Run methods. It is here we will check the original request. If our current object in the chain can handle the request...it will...otherwise we will pass on the request to the rest of the chain.

I am going to define a place where I can kick off the chain creation. This chain could also be created separately as part of some factory class.



public class ChainOfResponsibility
{
private ICommand stdOutLogger;

public void Initialize(int request)
{

stdOutLogger = new StdOutLogger(new EmailLogger(new StdErrLogger()));
stdOutLogger.Run(request);
}

}


The 'StdOutLogger' is the outmost part of the chain and will start everything off. Calling Run here...we will check the request. Let's say that the request is '3' coming from the Initialize method. StdOutLogger can't really handle this value...so it passes the request off to EmailLogger. EmailLogger's Run method can't handle this value either. The request is finally passed on to StdErrLogger which can handle three.

** Note that based on our code...once a request is dealt with no other command objects are called.**

Friday, January 25, 2008

Observer Pattern

Using a change observer in your application is really useful in windows forms applications where you have textboxes, checkboxes etc. that are inherently designed for event generation. A great implementation of the pattern is to observe a dirty property on your form letting you know if anything has changed.

A great starting point to learning the basics of the Observer pattern is on wikipedia. The subject (your form) will maintain a list of observers, remove observers from the list and notify all observers of any changes. Here is the interface for the subject.




public interface ISubject
{
void RegisterObserver(IObserver observer);
void UnRegisterObserver(IObserver observer);
void NotifyObservers();
}


When you implement this interface on your form, you create your observer and register it. For my purposes I only need to create one observer to monitor changes on any of my form controls. Here is the interface for the observer.





public interface IObserver
{
void Update();
bool IsDirty { get;}
}




As soon as a change occurs on any control I need to let the change observer know. So, whenever a TextChanged event occurs on my controls I can handle it and notify the change observer that something has happened by calling the NotifyObservers method.




public void NotifyObservers()
{
foreach (IObserver observer in changeObservers)
{
observer.Update
}
}


NotifyObservers will loop through all my registered observers and call the Update method. The Update method on the observer is really simple....it just flips the dirty property to true.

So now my form is dirty. If I happen to for example close my form without saving I can check with the changeobservers and see if there is anything dirty. If there is I can let the user know and ask if they want to save.





public void HandleFormClosing(object sender, CancelEventArgs e)
{
DialogResult result;

if (FormIsDirty)
{
result = MessageBox.Show
("You have unsaved Changes. Do you want to save?", "Unsaved", MessageBoxButtons.YesNoCancel);
if (result.Equals(System.Windows.Forms.DialogResult.Yes))
MessageBox.Show("Saved!");
else if (result.Equals(System.Windows.Forms.DialogResult.No))
MessageBox.Show("Not Saving!");
else
{
e.Cancel = true;

}
}
else
MessageBox.Show("No changes detected.");

}


One limiting feature of this implementation is that there is very little re-use.
I need to wire up all of my Handlers for each control on the form and then call NotifyObservers. If I have another form and want to do the same thing I have to write the same thing again. A better solution would be to push this event handling onto the ChangeObserver to register the controls and the event to fire whenever a change occurs.

public void RegisterControls(Control.ControlCollection controls)
{
foreach (Control control in controls)
{
if (control.GetType().Equals(typeof(TextBox)))
control.TextChanged += new EventHandler(HandleChange);
if (control.GetType().Equals(typeof(CheckBox)))
{
CheckBox checkbox = (CheckBox) control;
checkbox.CheckedChanged +=new EventHandler(HandleChange);
}
if (control.GetType().Equals(typeof(RadioButton)))
{
RadioButton radioButton = (RadioButton) control;
radioButton.CheckedChanged +=new EventHandler(HandleChange);
}
}
}

void HandleChange(object sender, EventArgs e)
{
Update();
}


So now I can reuse this code on any form that I want to observe.
If I have other types of controls I can throw them into the RegisterControls method.