Have you ever had that problem that you know you’ve solved before somewhere else? Many people have. Design Patterns are general solutions to specific problems that many people face. Design Patterns were first systematically organized for the C++ language in the book Design Patterns: Elements of Reusable Object-Oriented Software, by Erich Gamma et al. in 19952.
In general there are three kinds of Design Patterns: Creational, Structural, and Behavioral. Not only do they solve recurring problems, a formalized solution to a problem means that we don’t re-invent the wheel and that we can communicate more clearly about our code. Any programmer will (hopefully) recognize your use of pattern X and then know how to change your code accordingly.
In this chapter, I’m going to discuss a few (of many) Design Patterns. I’ll include a Unified Modeling Language (UML) class diagram of each pattern. UML is outside the scope of this book, so I can’t explain how the diagrams should be interpreted. I’ve added them for reference and they’re the “official” UML diagrams, so the class and method names don’t match those in the examples. You can use them for visual explanation, but if you don’t get them don’t worry, it’s all explained in the text.
The patterns I’m discussing are mentioned by the Design Patterns book as good starting patterns. They’re pretty easy to get into and you’ll probably use them a lot as well.
Creational Patterns
Creational Patterns deal with, as the name implies, the creation of objects. With Creational Patterns we can abstract away the process of object instantiation. As we’ve seen before, we can use composition rather than inheritance. Creating a set of objects that work together as a group can be beneficial, but rather than hard-coding which concrete types to use we can abstract this process like we’ve seen with DI. In the next section we’re going to look at a few Creational Patterns. It’s not a full list, but it shows the power they can bring.
Abstract Factory
One of the easiest, yet most useful, Creational Design Patterns is the Abstract Factory. The Abstract Factory defines an interface for the creation of closely related objects. Imagine, again, that we’re building a dynamic user interface. We need textboxes, buttons, checkboxes, radio buttons, etc. So let’s say we have the following Interface, analogous to the example I’ve used before, but in WinForms:
Code Listing 37: An Abstract Factory
public interface IControlFactory
{
Control CreateTextBox();
Control CreateCheckBox();
}
And let’s say it’s used as follows (which creates a pretty much unusable user interface):
Code Listing 38: Usage of the Abstract Factory
private void CreateGui(IControlFactory factory)
{
Control textBox = factory.CreateTextBox();
textBox.Location = new Point(10, 10);
Controls.Add(textBox);
Control checkBox = factory.CreateCheckBox();
checkBox.Location = new Point(10, 50);
Controls.Add(checkBox);
}
We can now create concrete types for this Interface.
Code Listing 39: Concrete Factories
public class RedControlFactory : IControlFactory
{
public Control CreateTextBox()
{
return new TextBox { BackColor = Color.Red };
}
public Control CreateCheckBox()
{
return new CheckBox { BackColor = Color.Red };
}
}
public class GreenControlFactory : IControlFactory
{
public Control CreateTextBox()
{
return new TextBox { BackColor = Color.Green };
}
public Control CreateCheckBox()
{
return new CheckBox { BackColor = Color.Green };
}
}
Now our application can create either a red or a green GUI using the specified concrete type.
Code Listing 40: Using the Concrete Factory
private void Form1_Load(object sender, EventArgs e)
{
CreateGui(new RedControlFactory());
}
The result is stunning:
And of course, changing RedControlFactory to GreenControlFactory changes the rendered Form from red to green.
Notice how easy it would be to add a BlueControlFactory without breaking any existing code? Or even better, we can swap our ugly WinForms controls with custom controls or with third party controls.
In .NET you can find the Abstract Factory Pattern when working with databases. The DbProviderFactory base class is such an Abstract Factory, although it’s typically not necessary to implement it yourself.
public class SqlProviderFactory : DbProviderFactory
{
public override DbConnectionStringBuilder CreateConnectionStringBuilder()
{
return new SqlConnectionStringBuilder();
}
public override DbConnection CreateConnection()
{
return new SqlConnection();
}
public override DbCommand CreateCommand()
{
return new SqlCommand();
}
// ...
}