Design Patterns in .NetIntroductionThe concept of a ‘Software Design Pattern’ was adopted from the idea of a building design pattern in the field of building design and architecture. Within the context of software engineering, a Design Pattern is the official term given to a design concept that encompasses the idea of reuse and communication. Simply stated, Design Patterns are tried and tested solutions to common and recurring challenges. At their core, design patterns are the manifestation of good object-oriented design principles.
Design Patterns are important to understand for the following reasons:
They give us reuse
Once a design pattern has emerged to solve a particular problem, that design pattern can be applied countless times on future tasks where a similar problem may arise. It can also be used by countless others who may encounter similar problems.
The give us a common taxonomy allowing for better communication
Design patterns allow one to refer to a design concept without explaining the full detail of that concept. How often has one heard a conversation along the lines of the following?
They give us a higher level of abstraction in terms of analysis and design
This allows one to think of the larger design in terms of smaller component areas. Therefore, when one looks at the bigger picture, one can visualize it in terms of its constituent parts.
Fosters design thinking
Creational PatternsFactory Pattern In .NET Factory pattern is one of the types of creational patterns. You can make out from the name factory itself it’s meant to construct and create something. In software architecture world factory pattern is meant to centralize creation of objects.
Factory Method Pattern defines an interface for creating an object, but let subclasses decide which class to instantiate. Below is a code snippet of a client which has different types of invoices. These invoices are created depending on the invoice type specified by the client.
Advantages:
Remove lots of ‘new’ keyword scattered in the client.
Client code is aware of both the concrete classes i.e. ‘InvoiceWithHeader’ and ‘InvoiceWithOutHeader’. To remove this issue we have introduced a common interface ‘IInvoice’. Both the concrete classes ‘InvoiceWithHeader’ and ‘InvoiceWithOutHeader’ inherit and implement the ‘IInvoice’ interface.
In order to avoid recompiling the client we have introduced the invoice interface ‘IInvoice’. Both the concrete classes ‘InvoiceWithOutHeaders’ and ‘InvoiceWithHeader’ inherit and implement the ‘IInvoice’ interface.
public interface IInvoice
{
void Print();
}
public class InvoiceWithHeader : IInvoice
{
public void Print()
{
Console.WriteLine("Invoice With Header.");
}
}
public class InvoiceWithOutHeader : IInvoice
{
public void Print()
{
Console.WriteLine("Invoice Without Header.");
}
}
public class FactoryInvoice
{
static public IInvoice GetInvoice(int invoiceType)
{
IInvoice _invoice;
if (invoiceType == 1)
_invoice = new InvoiceWithHeader();
else if (invoiceType == 2)
_invoice = new InvoiceWithOutHeader();
else
return null;
return _invoice;
}
}
class Program
{
static void Main(string[] args)
{
IInvoice _invoice;
Console.WriteLine("Enter Invoice Type:");
int invoiceType = Convert.ToInt32(Console.ReadLine());
_invoice = FactoryInvoice.GetInvoice(invoiceType);
_invoice.Print();
}
}
Abstract Factory Pattern In .NET Abstract Factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes. Abstract factory helps us to unite similar factory pattern classes in to one unified interface. So basically all the common factory patterns now inherit from a common abstract factory class which unifies them in a common class.
We can practically implement abstract factory in actual code. We have scenario where we have UI creational activities for textboxes and buttons through their own centralized factory classes ‘FactoryButton’ and ‘FactoryText’. Both these classes inherit from common interface ‘InterfaceRender’. Both the factories ‘FactoryButton’ and ‘FactoryText’ inherits from the common factory ‘AbstractFactory’. Figure ‘Example for AbstractFactory’ shows how these classes are arranged and the client code for the same. One of the important points to be noted about the client code is that it does not interact with the concrete classes. For object creation it uses the abstract factory ( AbstractFactory ) and for calling the concrete class implementation it calls the methods via the interface ‘InterfaceRender’. So the ‘AbstractFactory’ class provides a common interface for both factories ‘FactoryButton’ and ‘FactoryText’.
Figure ‘Common Interface for concrete classes’ how the concrete classes inherits from a common interface ‘InterFaceRender’ which enforces the method ‘render’ in all the concrete classes.
public interface IInterfaceRender
{
void Render();
}
public class TextBox : IInterfaceRender
{
public void Render()
{
Console.WriteLine("The Textbox is Rendered.");
}
}
public class Button : IInterfaceRender
{
public void Render()
{
Console.WriteLine("The Button is Rendered.");
}
}
Factory pattern classes inherit from abstract factory.
public abstract class AbstractFactory
{
static public IInterfaceRender GetUIObject(int objectType)
{
if (objectType == 1)
return FactoryTextBox.GetTextBoxObject();
else
return FactoryButton.GetButtonObject();
}
}
public class FactoryTextBox : AbstractFactory
{
static public IInterfaceRender GetTextBoxObject()
{
return new TextBox();
}
}
public class FactoryButton : AbstractFactory
{
static public IInterfaceRender GetButtonObject()
{
return new Button();
}
}
The final thing is the client code which uses the interface ‘InterfaceRender’ and abstract factory ‘AbstractFactory’ to call and create the objects. One of the important points about the code is that it is completely isolated from the concrete classes. Due to this any changes in concrete classes like adding and removing concrete classes does not need client level changes.
class Program
{
static void Main(string[] args)
{
IInterfaceRender objUIObject;
Console.WriteLine("Enter which object you want to render:");
int objectType = Convert.ToInt32(Console.ReadLine());
objUIObject = AbstractFactory.GetUIObject(objectType);
objUIObject.Render();
}
}
Builder Pattern In .NET Builder pattern helps us to separate the construction of a complex object from its representation so that the same construction process can create different representations. Builder pattern is useful when the construction of the object is very complex. The main objective is to separate the construction of objects and their representations. If we are able to separate the construction and representation, we can then get many representations from the same construction.
Now let’s take a real time example in software world to see how builder can separate the complex creation and its representation. Consider we have application where we need the same report to be displayed in either ‘PDF’ or ‘EXCEL’ format. Figure ‘Request a report’ shows the series of steps to achieve the same. Depending on report type a new report is created, report type is set, headers and footers of the report are set and finally we get the report for display.
Now let’s take a different view of the problem as shown in figure ‘Different View’. The same flow defined in ‘Request a report’ is now analyzed in representations and common construction. The construction process is same for both the types of reports but they result in different representations.
We will take the same report problem and try to solve the same using builder patterns. There are three main parts when you want to implement builder patterns.
Builder - Builder is responsible for defining the construction process for individual parts. Builder has those individual processes to initialize and configure the product.
Director - Director takes those individual processes from the builder and defines the sequence to build the product.
Product - Product is the final object which is produced from the builder and director coordination.
Figure ‘Builder classes in actual code’ shows the methods of the classes. To generate report we need to first Create a new report, set the report type (to EXCEL or PDF) , set report headers , set the report footers and finally get the report. We have defined two custom builders one for ‘PDF’ (ReportPDF) and other for ‘EXCEL’ (ReportExcel). These two custom builders define there own process according to the report type.
The third component in the builder is the product (Report)
public class Report
{
public string reportType;
private ArrayList objHeader = new ArrayList();
private ArrayList objFooter = new ArrayList();
public void SetReportHeader(string date) { }
public void SetReportFooter(string date) { }
public void DisplayReport() { }
}
We have defined two custom builders one for ‘PDF’ (ReportPDF) and other for ‘EXCEL’ (ReportExcel).
public abstract class ReportBuilder
{
protected Report _report;
public void CreateNewReport() { }
public abstract void SetReportType();
public abstract void SetReportHeader();
public abstract void SetReportFooter();
public Report GetReport()
{
return new Report();
}
}
public class ReportPDF : ReportBuilder
{
public override void SetReportType() { }
public override void SetReportHeader() { }
public override void SetReportFooter() { }
}
public class ReportExcel : ReportBuilder
{
public override void SetReportType() { }
public override void SetReportHeader() { }
public override void SetReportFooter() { }
}
Class ‘Director’ takes the builder and calls the individual method process in a sequential manner. So director is like a driver who takes all the individual processes and calls them in sequential manner to generate the final product, which is the report in this case. Figure ‘Director in action’ shows how the method ‘MakeReport’ calls the individual process to generate the report product by PDF or EXCEL.
public class Director
{
public Report MakeReport(ReportBuilder reportBuilder)
{
reportBuilder.CreateNewReport();
reportBuilder.SetReportType();
reportBuilder.SetReportHeader();
reportBuilder.SetReportFooter();
return reportBuilder.GetReport();
}
}
Now let’s take a top view of the builder project. Figure ‘Client,builder,director and product’ shows how they work to achieve the builder pattern. Client creates the object of the director class and passes the appropriate builder to initialize the product. Depending on the builder the product is initialized/created and finally sent to the client.
class Program
{
static void Main(string[] args)
{
Report _report = new Report();
Director _director = new Director();
ReportPDF reportPDF = new ReportPDF();
_report = _director.MakeReport(reportPDF);
_report.DisplayReport();
ReportExcel reportExcel = new ReportExcel();
_report = _director.MakeReport(reportExcel);
_report.DisplayReport();
}
}
Structural Patterns
Proxy Design Pattern In .NET Reference: http://aspalliance.com/827_Gang_of_Four_GOF_Design_Patterns.6
The Proxy design pattern shows a way to do just-in-time loading of objects that would consume too much memory to keep around or take too much time to load. This can be a very useful pattern for many applications. A good example of this pattern is in Microsoft Office. When you open a large Word document that has many embedded pictures, Office does not load them all at the time you open the document. As you scroll down, Office will pull the pictures from the disk file and insert them into the document. You can see this by scrolling very fast down the document. It takes a second or so for the document to “catch up” to you and show the visible images.
For our example, we will have a part object that represents a manufacturer's part in a database. It has a FullDescription property that could be many pages of text. We do not want to load this text unless the user really wants to see it.
We first start by creating a wrapper for the description. It is a very simple object that just exposes the text we want to return. In a real world application the text would come from a database or something similar.
public class PartDescription
{
private string _PartNumber;
private string _PartText;
public PartDescription(string PartNumber)
{
_PartNumber = PartNumber;
//load text now For the demo, we just make sometext up.
if (_PartNumber == "1")
{
_PartText = "Pages of text for part1";
}
else if (_PartNumber == "2")
{
_PartText = "Pages of text for part2";
}
else
{
_PartText = "Part Not Found";
}
}
public string ReturnText
{
get { return _PartText; }
}
}
The Part class is also simple. It just allows entry of the part number and then has a method to return the part text.
The interesting method is FullDescription. You will see that the get method first checks to see if the _PartDescription object is null or not. If not, then we do not need to create the object as it has already been done before. If we do not need the text after the call, we can set the object to null after returning the text. This would be useful if we did not want to keep the overhead of the part text around. After passing the text to some other program, we can clear it in our object. Here is the rewrite of the function.
public class Part
{
private string _PartNumber;
private PartDescription _PartDescription;
public Part()
{
_PartDescription = null;
}
public string PartNumber
{
get { return _PartNumber; }
set { _PartNumber = value; }
}
public string FullDescription
{
get
{
if (_PartDescription == null)
{
_PartDescription = new PartDescription(_PartNumber);
}
return _PartDescription.ReturnText;
}
}
}
We have added error handling in this function to allow for a finally block to null the object.
Behavioral PatternsCommand Pattern in .NETThe command pattern is a very useful pattern when you want to give your users the ability to do certain things and undo them. Typical examples are the undo and redo on many programs today. This functionality is accomplished with the command pattern. The GOF book says to use a command pattern when:
1. Parameterize objects by an action to perform
2. Specify, queue, and execute requests at different times
3. Support undo (GOF235)
The pattern encapsulates the commands of your application to self contained classes. For our example, we will revisit the dog example I have used before and play God for a while. Our operations will be to magically increase and decrease our bulldog's age. Since we are almighty, we of course can change our minds and undo our meddling.
First we start with a very simple Bulldog class.
public class CBulldog
{
private int _Age;
private string _BarkString;
public CBulldog()
{
_Age = 0;
_BarkString = "Woof";
}
public void Bark()
{
Console.WriteLine(_BarkString);
}
public int MyAge
{
get { return _Age; }
set { _Age = value; }
}
public string MyBark
{
get { return _BarkString; }
set { _BarkString = value; }
}
}
All the class does is to keep up with the dog’s age, provide a method to change it and allows for the dog to bark. The bark method writes the dog's bark out to the console window.
For our command classes, we first define three interfaces then our main command classes. The interfaces allow different kinds of commands to be acted upon as the same type of class. For our example, we will use two different commands, one to change the dog’s age and another to change how he barks.
First we create our interfaces:
public interface IBaseCommand
{
void Undo();
}
public interface IAgeCommand : IBaseCommand
{
void AddAge(int age);
}
public interface IBarkCommand : IBaseCommand
{
void ChangeBark(string Newbark);
}
We base the two main command interfaces of a generic one that allows for an undo. This will allow us to iterate over all interfaces later and undo them as a group. We can cast any IAgeCommand or IBarkCommand down to an IBaseCommand.
Now for our two classes that encapsulate the commands. They are pretty straight forward. Each takes a parameter of the dog to operate on in the constructor and saves off any relevant information like the last age, etc.
public class AgeCommand : IAgeCommand
{
private CBulldog _OurDog;
private int _OldAge;
public AgeCommand(CBulldog o)
{
_OurDog = o; //dog to work on
}
public void AddAge(int age)
{
_OldAge = _OurDog.MyAge;
_OurDog.MyAge = age;
}
public void Undo()
{
_OurDog.MyAge = _OldAge;
}
}
public class BarkCommand : IBarkCommand
{
private CBulldog _OurDog;
private string _OldBark;
public BarkCommand(CBulldog o)
{
_OurDog = o; //dog to work on
}
public void ChangeBark(string Newbark)
{
_OldBark = _OurDog.MyBark;
_OurDog.MyBark = Newbark;
}
public void Undo()
{
_OurDog.MyBark = _OldBark;
}
}
Our test of the code will be to create a dog, show its initial settings, change them, show the new settings and then revert back to the original. For simplicity, we store the list of used commands in an ArrayList object.
class Program
{
static void Main(string[] args)
{
CBulldog oDog;
ArrayList cmd = new ArrayList();
oDog = new CBulldog();
AgeCommand a1 = new AgeCommand(oDog);
Console.WriteLine(oDog.MyAge.ToString());
a1.AddAge(4);
cmd.Add(a1);
Console.WriteLine(oDog.MyAge.ToString());
BarkCommand b1 = new BarkCommand(oDog);
oDog.Bark();
b1.ChangeBark("Yip Yip");
cmd.Add(b1);
oDog.Bark();
//at this point we have a dog that as beenchanged
//we also have an array that has the command
//objects that were used for the change.
//To undo, just loop through the arraylistbackwards
cmd.Reverse();
foreach (IBaseCommand bse in cmd)
{
bse.Undo();
}
oDog.Bark();
Console.WriteLine(oDog.MyAge.ToString());
}
}
Strategy Pattern in .NETFrequently with applications, many of the operations they perform are dynamic depending on several factors. Think about a common scenario, Sales Tax. Tax amounts are based off the place where you live. There are many different tax rates in each country. A good method of implementing dynamic patterns like taxes is needed. The strategy pattern covers this gap for us.
The strategy pattern is very useful when a dynamic formula or data is needed. In our situation it will allow us to swap out different tax objects when needed. The pattern lets a class take on many different behaviors depending on the context in which it is used.
The strategy patterns starts with an interface that defines the methods that each different behavior defines. Our tax interface is simple, only one method that returns the (full amount of the price) * (the tax amount).
public interface ITaxStrategy
{
double CalculateTax(double amount);
}
This interface will be implemented in all of our tax strategy classes to give them a common base.
Two simple classes are then created for calculating taxes for the USA and the UK. Both tax rates are made-up, 5% for the USA and 7% for the UK.
public class USATax : ITaxStrategy
{
public USATax() { }
public double CalculateTax(double amount)
{
return amount * 1.05;
}
}
public class UKTax : ITaxStrategy
{
public UKTax() { }
public double CalculateTax(double amount)
{
return amount * 1.07;
}
}
To demonstrate the use of the two classes, we will create a simple inventory item class that represents an item in our stores inventory. The class will hold the price of the item.
public class InventoryItem
{
private ITaxStrategy _ItemTax;
private double _ItemAmount;
public InventoryItem() { }
public void SetTax(ITaxStrategy tax)
{
_ItemTax = tax;
}
public double ItemAmount
{
get { return _ItemAmount; }
set { _ItemAmount = value; }
}
public double ItemWithTax
{
get
{
return _ItemTax.CalculateTax(_ItemAmount);
}
}
}
Now let us examine the code that makes the class use the strategy pattern. A private variable named _ItemTax is declared as type ITaxStrategy. This is our internal representation of which strategy we want the class to use. The SetTax method allows us to set whichever strategy object we need to the inventory item. The property ItemWithTax returns the item’s amount with the tax added into it by calling the CalculateTax method on our strategy object.
To see the classes in motion the following code can be used.
class Program
{
static void Main(string[] args)
{
InventoryItem itm;
itm = new InventoryItem();
itm.ItemAmount = (double)10;
USATax usaTax;
usaTax = new USATax();
UKTax ukTax;
ukTax = new UKTax();
itm.SetTax(usaTax);
Console.WriteLine(itm.ItemWithTax.ToString());
itm.SetTax(ukTax);
Console.WriteLine(itm.ItemWithTax.ToString());
}
}
The first thing we do is create an object of the InventoryItem class. We then create a US tax object and a UK tax object. After setting the tax object to our inventory class, the message boxes show the result. You will get 10.5 for the first tax and 10.7 for the second, showing the different strategies in action.
While this is just a demonstration, in a real world application the tax objects would be created dynamically based on a registry key, configuration file, or based on the findings of a reflection call. One technique I have used is to use reflection to query the install directory for a class that implements the ITaxStrategy interface. When the product is installed, the user chooses what region they are in and the correct dll with the tax class is installed. Reflection can then find this class and create an instance of it on the fly to pass to the inventory class.
Visitor Design Pattern In .NETReference: http://aspalliance.com/827_Gang_of_Four_GOF_Design_Patterns.3
The visitor design pattern is very useful in situations in which normal polymorphism will not work because we have fundamentally different objects, with different interfaces, that you want to work on your concrete main object. The pattern is used to give us a way to do these different operations on the object. According to the GOF book, you use the visitor pattern when:
An object structure contains many classes of objects with differing interfaces and you want to perform operations on these objects that depend on their concrete classes.
Many distinct and unrelated operations need to be performed on objects in an object structure and you want to avoid "polluting" their classes with these operations. Visitor lets you keep related operations together by defining them in one class. When the object structure is shared by many applications, use Visitor to put operations in just those applications that need them.
The classes defining the object structure rarely change, but you often want to define new operations over the structure. Changing the object structure classes requires redefining the interface to all visitors, which is potentially costly. If the object structure classes change often, then it is probably better to define the operations in those classes (GOF333).
We first start by defining a base class for our visitor object collection. We will use our common Cbulldog object for our example.
public class BaseVisitor
{
public BaseVisitor() { }
public virtual void VisitBulldog(CBulldog dog){}
}
The code is pretty simple, having only a single method that takes an instance of the bulldog to work on. We can then derive concrete instances of visitors from this base. We will derive two for our example, one that changes our dog’s age and another that changes his bark. First we will look at our Cbulldog class. It has not changed much; there is only one new method.
public class CBulldog
{
private int _Age;
private string _BarkString;
public CBulldog()
{
_Age = 0;
_BarkString = "Woof";
}
public void TakeVisitor(BaseVisitor bv)
{
bv.VisitBulldog(this);
}
public void Bark()
{
Console.WriteLine(_BarkString);
}
public int MyAge
{
get { return _Age; }
set { _Age = value; }
}
public string MyBark
{
get { return _BarkString; }
set { _BarkString = value; }
}
}
The TakeVisitor method allows our class to accept any visitor that is derived from BaseVisitor. The method simply calls the VisitBulldog method and passes a pointer to the current class.
Now we look at our concrete derived visitor classes. First, the class that will change the dog’s age:
public class AgeVisitor : BaseVisitor
{
public AgeVisitor() : base() { }
public override void VisitBulldog(CBulldog dog)
{
dog.MyAge = 5;
}
}
This class that will change his bark.
public class BarkVisitor : BaseVisitor
{
public BarkVisitor() : base() { }
public override void VisitBulldog(CBulldog dog)
{
dog.MyBark = "Yip Yip";
}
}
As you see, all that the methods do are to act upon the dog object passed to them. You can make them as complex or simple as needed.
Our test code for the example:
class Program
{
static void Main(string[] args)
{
CBulldog Mydog;
Mydog = new CBulldog();
Mydog.Bark();
Console.WriteLine(Mydog.MyAge.ToString());
AgeVisitor av;
av = new AgeVisitor();
Mydog.TakeVisitor(av);
Console.WriteLine(Mydog.MyAge.ToString());
BarkVisitor bv;
bv = new BarkVisitor();
Mydog.TakeVisitor(bv);
Mydog.Bark();
}
}
If you watch the output window, you will see that the calls to TakeVisitor change the dog’s information.
This pattern can help keep your objects cleaner when there are many different types of visitors you want to use.