Learning anything new often requires a little motivation. The premise of design patterns is simple – effective solutions to common design problems. Moreover these solutions have been battle tested in the field for many years. The result of this is that for many design scenarios there exists a design pattern.
Design Patterns Series
Part 1 Learn how to design more robust and maintainable code by incorporating design patterns into your software projects.
Part 2 This part shows the observer design pattern.
Part 3 In this part you will learn about the factory pattern.
Part 4 This part of the design patterns covers the singleton pattern.
Part 5 In this part of the design patterns series we investigate the command pattern and its uses.
Part 6 In this part of the design patterns series we will look at the adapter pattern.
Part 7 In this part of the design patterns series we will take a look at the template pattern.
Most design patterns are not trivial; they have taken someone (or a group of people) many hours to perfect. What is even more compelling is that they have published their work so you don’t have to waste your time solving the same problem.
Design patterns differ to what could be considered primitive object oriented (OO) concepts. While they fully take advantage of everything that OO has to offer, they also introduce solutions that at the time may not be very obvious. As a direct result of this many who are very comfortable with OO don’t employ such patterns. Most are aware that OO principles can be used in many scenarios to design fairly elegant solutions to problems; however design patterns have a tendency to scale a lot better. Because design patterns scale gracefully while remaining simple to maintain you will find them used in many frameworks and applications.
Throughout this series I will use UML diagrams to describe the structure of the design pattern in question. We will purposely avoid class diagrams so that others who are perhaps not familiar with the Microsoft development platforms can utilize this series. UML provides a common language that most developers, irrespective of their language and platform understand.
In this series we will look at the most common design patterns. This part will cover a simple design pattern to emphasize the elegance of their application, and to act as motivation for reading the rest of this series.
The strategy pattern
The strategy pattern is built around being able to accommodate an interchangeable family of algorithms, or more aptly components. These components have varying implementations. One of the design principles’ is to separate everything that varies. The strategy pattern provides an elegant solution to such a problem.
In this article we will look at a simple example. The example we will look at is based upon a car and its engine. Different cars have different engines; each engine behaves differently when its engine is started. Some engines will make you marvel at the engineering skills of man, others will make you curse them.
Each car will have its own class, all car’s will derive from the abstract class
Figure 1: Basic outline of the class design structure
The main problem is that the engine varies for each car. The engine in a Ferrari Enzo is far different than that of a Ford Escort. What we have here is a very simple case of where the implementation will vary. All engines will exhibit slightly different behavior and so we want to separate this from that which doesn’t vary for all cars.
At this stage let’s go ahead and design an interface (we’ll program to an interface here, not an implementation) which will define the behavior all engines must have. For our simple example, and to keep the focus on the pattern we will create an interface
IEngine that only has one method
Figure 2: The IEngine interface
Now that we have our interface we will define an additional two types:
EscortEngine both of which will implement
IEngine. We will also add an attribute to the Car class that is of type
IEngine, as well as a
Figure 3: Our final solution design
Of course the example we are working through is very simple to keep focus on the actual pattern we are designing. In reality a Car type may have several other properties like the number of doors, the type of gearbox etc.
So far we have not talked about the
Start method in the
Car class. This
Start method will delegate the start engine behavior to the actual object. Ex: when we create a new instance of
Enzo class will initialize the value of
m_engine to an
EnzoEngine. When the
Start method of
Car is invoked the
Start method of
EnzoEngine will be called. Similarly in
Escort the value of
m_engine will be initialized to
EscortEngine and its
Start method will be invoked upon calling the
Start method in
Car. The implementation of this behavior is simple in
Start method will contain the imperative
We mentioned earlier that the strategy pattern enables the interchanging of a family of algorithms. In our example this family of algorithm is all the types that implement
IEngine. For instance should our program require so we could upgrade the engine in our
Escort and swap in an
EnzoEngine at run time.
Implementing our design
Implementing the design we have discussed thus far is really very trivial. For purposes of illustration we will use a Console Application and print messages to the Console from both the
EscortEngine Start methods to differentiate between the two.
Listing 1: IEngine.cs
Listing 2: EnzoEngine.cs
Listing 3: EscortEngine.cs
Listing 4: Car.cs
Listing 5: Enzo.cs
Listing 6: Escort.cs
Listing 7: Program.cs
Running the application results in the expected output – one car sounds like its amazing, the other making wished you had never bought it.
Figure 4: Delegated behavior to the respective engine objects
The strategy pattern allows for a family of interchangeable algorithms. These algorithms can be interchanged freely with no effect on the design; the correct behavior is delegated to the actual object. As demonstrated in this article all behavior that varies, e.g. the engines have been isolated from that which doesn’t vary. Each engine is programmed to an interface not an implementation, although you could use an abstract class.
The beauty of the strategy pattern is its simplicity. We have a robust and maintainable design that can be further extended in the future, yet the design is incredibly simple.
In the next article we will look at the observer pattern which is a lot more fun!
Sorry, no bio is available
This author has published 32 articles on DotNetSlackers. View other articles or the complete profile here.
Other articles in this category
Introduction to StructureMap
Have you heard of StructureMap, generally know what it’s for, and want to know how to get started qu...
The Command Pattern
In this article I will provide a quick refresher on what the command pattern is used for, how it wor...
DI Patterns: Constructor Injection
In this article, an excerpt from the book "Dependency Injection in .NET", we will take a detailed lo...
Brian Mains discusses how to implement the Arrange-Act-Assert pattern in TypeMock.
Key Process Patterns
This article, based on chapter 2 of Specification by Example, presents effective patterns for softwa...
You might also be interested in the following related blog posts
Learn design patterns from real projects: JBoss case study (Part 1).
Designing a Windows 8 Metro style app starting from an existing Windows Phone app Design Case Study Part 1
Introducing SharePoint 2010 Training at U2U
The Underground at PDC
12 ASP.NET MVC Best Practices
Screencast Whats new in the Entity Data Model Designer in VS2010
What needed to be monitored to get better Governance
SharePoint 2010 Workflow
Formatting Text in RadControls for WinForms Q3 2009
Please login to rate or to leave a comment.