|
Introduction - What are Design Patterns?
In order to understand what design patterns are, you first need a basic understanding of what software development really is. At its core, software design and development is nothing more than an attempt to solve a problem, usually a business or scientific one, using computing. This is the reason we refer to software as solutions. There have been millions of software solutions created to solve just as many problems. Many of these problems are identical, or similar enough to be nearly identical. In most cases, there are usually several potential solutions to any one of these problems. However, all solutions are not created equal, and the design for a solution is as important, if not more so, than the code that actually implements that solution. Problems change and evolve, and the solutions that solve those problems must be able to change and adapt easily if they are going to be of any real value. A good design supports the development of software that is able to adapt and change easily as the problem it is solving changes. A good design also provides the ability to reuse aspects of the solution in other places. This is the basis for why Design Patterns were created. They provide well defined, flexible, time tested solutions to the common problems that software attempts to solve.
Design Patterns are nothing new. They have been around for decades. They can be implemented in nearly any object oriented language. They require little more than an understanding of the problem you are trying to solve and an understanding of the pattern that solves that problem. As mentioned previously, they use designs that have been tried and tested and have shown themselves to be good solutions for the respective problems that they solve. There are literally hundreds of design patterns that have been defined. The most well known design patterns were defined by a group of talented software designers now known as “The Gang of Four”. Having a good repertoire of design patterns under your belt means that when you are presented with a problem, you don’t need to spend as much time figuring out how to solve it. You simply identify the problem and apply the pattern to it. They also give you a common base of terminology with which to describe your solution to other developers that are helping to solve the problem. If you are working with a group of developers that are familiar with design patterns, you don’t have to spend time explaining the intricacies of a solution; you need only specify the pattern you think best solves the problem. If everyone is familiar with the pattern you are proposing, you are much further along in the design process. Best of all, you know that because you used a pattern, your solution has a decent chance of being a good one.
Having said all that, let’s take a look at a design pattern, the Decorator Pattern. The decorator pattern solves problems where you have an object whose state or behavior can be modified by other objects that attach to or “decorate” it. Examples of this would be pizzas and their toppings, cars and their options, or streams and what to read or write to and the format they do it in. To help this make more sense, let’s take a look at a solution to a problem where we need the ability to decorate a base car with one or more non-standard features in order to come up with its sale price and description.
Using the code

- The first thing that we have to do is define a common type that will be used for both the cars themselves and the options we will use to decorate the cars with. This type will be the base for all of the cars that we will decorate. To do that, we create the following:
(It should be noted that it is not necessary to define both an interface for cars and an abstract, one or the other or both will suffice. What to use depends solely on the design considerations of your application.)
interface ICar
{
double Cost {get;}
string Description { get; }
}
abstract class Car:ICar
{
private double _cost = -1;
private string _desc = "abstract car.";
public virtual double Cost
{
get { return _cost; }
}
public virtual string Description
{
get { return _desc; }
}
}
- After we have defined the base functionality for our cars and their options, we need to define a base type for the options themselves:
abstract class CarOption:Car
{
double _cost = -1;
string _desc = "abstract car option";
public override string Description
{
get { return _desc; }
}
public override double Cost
{
get { return _cost; }
}
}
CarOption (above) implements Car and overrides its behavior. This type will be the base for all the classes that we will use to decorate a car with.
- Now, we will create a concrete implementation of a car:
class FerrariSpider:Car
{
double _cost = 250000;
string _description = "Ferrari Spider";
public override double Cost
{
get
{
return _cost;
}
}
public override string Description
{
get
{
return _description;
}
}
}
We have created a FerrariSpider class which implements our base Car class and overrides its behavior with the Ferrari specific behavior, namely the cost and desciption of a Ferrari Spider with no options.
- Now, we need to define some options that we want to decorate our Ferrari with:
We are going to create Turbo, Alloy Wheels, and Leather options for our Ferrari (or any other car that we might want to use them on).
class OptionAlloyWheels : CarOption
{
double _cost = 4564.42;
string _description = "Alloy Wheels, ";
Car _car;
public OptionAlloyWheels(Car car)
{
_car = car;
}
public override double Cost
{
get
{
return _car.Cost + _cost;
}
}
public override string Description
{
get
{
return _car.Description + _description;
}
}
}
class OptionTurbo:CarOption
{
double _cost = 7000.24;
string _description = "Turbo, ";
Car _car;
public OptionTurbo(Car car)
{
_car = car;
}
public override double Cost
{
get
{
return _car.Cost + _cost;
}
}
public override string Description
{
get
{
return _car.Description + _description;
}
}
}
class OptionLeather : CarOption
{
double _cost = 1000;
string _description = "Leather Seats, ";
Car _car;
public OptionLeather(Car car)
{
_car = car;
}
public override double Cost
{
get
{
return _car.Cost + _cost;
}
}
public override string Description
{
get
{
return _car.Description + _description;
}
}
}
Each of our options implement our CarOption class and override its default behavior. Each option also has a local reference to a Car type that will be used to hold a reference to the car that is to be decorated. The car instance is handed to the option via the option’s constructor.
- All that is left to be done now is to create an instance of our spider and give it some options by decorating it with the various option classes that we have created.
class Program
{
static void Main(string[] args)
{
Car car = new FerrariSpider();
car = new OptionLeather(car);
car = new OptionAlloyWheels(car);
car = new OptionTurbo(car);
Console.WriteLine("Description-->" +
car.Description.TrimEnd(' ',','));
Console.WriteLine("Cost-->" +
car.Cost.ToString());
Console.ReadLine();
}
}
Running this should produce the following:

Why this is cool
Creating the cars and their options separate from each other makes them very reusable. Any option can be used to decorate any car so long as the specific car implements Car or ICar and the specific car option implements CarOption. Because each car and each option are encapsulated in their own classes, there is no danger of breaking other cars or options when modifications to a specific car or option is needed. For the same reason, we can add new cars and options without fear of breaking existing implementations. Options already defined can be easily reused for new cars that are created. Going the other way, if new options are defined for existing cars, there is no need to modify the code for the car itself. Decorating a car with options in this manner is very easy, and creates very clean, readable, maintainable code. All you have to do is create an instance of the car you want to decorate and pass its instance to the constructor of any option you want to decorate the car with.
History
- Jan-2-2006 -- Initial creation.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 21 of 21 (Total in Forum: 21) (Refresh) | FirstPrevNext |
|
 |
|
|
Hi,
I am just understanding the concept of the decorator pattern. And this article very much helped me in fact.
Have one question. This came to my mind when i was implementing it.
Do we really need the CarOption class? Can you please explain the scenario where it will be breaking if we don't use CarOption.
My idea is that the classes OptionAlloyWheels, OptionLeather can derive from Car itself rather than deriving from CarOption. Is that fine as per the pattern ? Please provide your valuable comments for my question.
regards,
Sunil
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I can't say this 100% correct but here is my first attempt to convert this over...
Public Interface ICar ReadOnly Property Cost() As Double ReadOnly Property Description() As String
End Interface
Public MustInherit Class Car : Implements ICar Private _cost As Double = -1 Private _desc As String = "abstract car."
Public Overridable ReadOnly Property Cost() As Double Implements ICar.Cost Get Return Me._cost End Get End Property
Public Overridable ReadOnly Property Description() As String Implements ICar.Description Get Return Me._desc End Get End Property End Class
Public MustInherit Class CarOption : Inherits Car Private ReadOnly _desc As String Private ReadOnly _cost As Double
Public Overrides ReadOnly Property Cost() As Double Get Return _cost End Get End Property
Public Overrides ReadOnly Property Description() As String Get Return _desc End Get End Property
End Class
Public Class OptionAlloyWheels Inherits CarOption
Private ReadOnly _cost As Double = 4564.42 Private ReadOnly _description As String = " Alloy Wheels"
Private _car As Car
Public Sub New(ByVal car As Car) _car = Car End Sub
Public Overrides ReadOnly Property Cost() As Double Get Return _car.Cost + _cost End Get End Property Public Overrides ReadOnly Property Description() As String Get Return _car.Description + _description End Get End Property End Class
Public Class FerrariSpider : Inherits Car
Private ReadOnly _cost As Double = 250000 Private ReadOnly _description As String = "Ferrari Spider"
Public Overrides ReadOnly Property Cost() As Double Get Return _cost End Get End Property Public Overrides ReadOnly Property Description() As String Get Return _description End Get End Property
End Class
Warren LaFrance
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
As the subject says IMHO the article would have been far more clear if the decorater classes would have been named "CarWith..." instead of only "Car...".
The current naming breaks the good old "Is A" rule of thumb for identifying inheritance (and the class diagramm simply loks plain wrong at first glance)...
Besides this point of critic the article covers the idea of the decorator pattern really good, but somehow ... I lack the fantasy for any real example for this. Simply trying to persist the cars in the example used here lets me end up with an Aggregation for CarOptions, and the Decorator pattern is gone (no more "With" here =))....
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
This is a good article and I don't understand why it got canned. The main problem I see with this article is that it doesn't clearly state why the decorator pattern can be useful.
Why is it useful? You can add a specialized functionality to an instance of an object without modifying that object and reuse that object's functionality.
Why not use inheritance to accomplish this? You could but there are some disadvantages to this approach.
1. You'll end up with a bunch of specialized classes with long and complicated names because you'll try to combine decorations into a derived class i.e. LeatherTurboAlloyWheelsTurboCar. 1. All instances of your derived class are forced to have this specialized functionality. Decorator objects on the other hand modify the decorated object's instance not its class. 2. If you have many specialized objects that mix and match other specializations you will be stuck with a complicated inheritance scheme.
Why not stick all the "decorations" in the base class? You could but you're going the "if else if else" way to process all the options which is not the object oriented way. Try drawing all the options in the car example instead of just changing the description and you'll pull your hair out.
In essence, decorator objects can reduce this design complexity by modifying their contained object's behavior without inheriting directly from them while still reusing their code.
Here are a few guidelines for using decorators. The base class inherited by the decorated object and the decorator should be simple so that decorators don't get bloated. If you use too many decorators you're headed for a maintenance nightmare because it will become hard to know which decorators do what.
To recap. Do you have lots of little specialized objects that make modifications to certain instances of their associated base objects? Use the decorator pattern.
The beginning of the article linked to by Charl made me understand the WHY of decorator patterns: http://www.awprofessional.com/articles/article.asp?p=31350&rl=1
My thanks to Eric Ray for his article. It got me thinking about design patterns and I think that was the author's main goal anyway.
Sidenote: Put the contained object "Car _car" in the CarOption class not in the derived classes. Liu Junfeng has done this in his "refactored" version.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
The problem I had with the pattern as defined in Eric's article was the following:
abstract class CarOption:Car
I followed the link you provided and read the article there carefully, and finally got it. The pattern does not require that the decorator class be derived from the class it is decorating. Quoting from the article[^] you linked to:
Instead, we create a Decorator class that decorates the buttons. Then we derive any number of specific Decorators from the main Decorator class, each of which performs a specific kind of decoration. In order to decorate a button, the Decorator has to be an object derived from the visual environment so it can receive paint method calls and forward calls to other useful graphic methods to the object it is decorating. This is another case where object containment is favored over object inheritance. The Decorator is a graphical object, but it contains the object it is decorating. It may intercept some graphical method calls, perform some additional computation, and pass them on to the underlying object it is decorating.
Note that the article indicates that the decorator class contains the object it is decorating, as opposed to Eric's derivation from the object it is decorating. I'm totally OK with the design pattern under these circumstances.
Tom Clement Serena Software, Inc. www.serena.com
articles[^]
-- modified at 15:15 Wednesday 18th January, 2006
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Could you please share your experience of how to create such cool-looking UML diagrams? I mean, what software do you use? I used to use MSVisio for these purposes, but your ones look much more attractive.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Yes, juanpablobg is correct. The diagram is one of my favorite features of Visual Studio 2005. I am using the architect version. I don't believe the diagram builder is available in all version of the IDE.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
/// /// Provides the base type for concrete cars and concrete car options /// abstract class Car:ICar { protected double _cost = -1; protected string _desc = "abstract car. ";
public Car(double cost, string desc) { _cost = cost; _desc = desc; }
#region ICar Members
public virtual double Cost { get { return _cost; } }
public virtual string Description { get { return _desc; } }
#endregion }
/// /// Provides a concrete implementation of the Ferrri Spider car. /// class FerrariSpider : Car { public FerrariSpider() : base(250000, "Ferrari Spider ") { } } /// /// Provides the base type for concrete car options that will be used to decorate concrete cars /// abstract class CarOption : Car { protected Car _car; public CarOption(Car car, double cost, string desc) : base(cost, desc) { _car = car; }
public override double Cost { get { return _car.Cost + _cost; } }
public override string Description { get { return _car.Description + _desc; } } } /// /// Provides a concrete implementation of the Alloy Wheels car option. /// class OptionAlloyWheels : CarOption {
public OptionAlloyWheels(Car car) : base(car, 4564.42, "Alloy Wheels, ") { } } /// /// Provides a concrete implementation of the Turbo car option. /// class OptionTurbo:CarOption { public OptionTurbo(Car car) : base(car, 7000.24, "Turbo, ") { } } /// /// Provides a concrete implementation of the Leather car option. /// class OptionLeather : CarOption { public OptionLeather(Car car) : base(car, 1000, "Leather Seats, ") { } }
-- modified at 0:24 Monday 16th January, 2006
|
| Sign In·View Thread·PermaLink | 5.00/5 (3 votes) |
|
|
|
 |
|
|
I just came accross this article and was curious to see how it was explained. It is good, but I didn't like the example code. Liu, you nailed it. This is how it was supposed to be implemented. Now the article and the code make more sense. Nick
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
Hi Eric,
Thank you for the article. I'm trying to understand a bit more about this pattern. I get it that you might have implemented the list of options as an ArrayList or something (instead of embedding it in the string), and that in a real implementation, you would probably have done this so that you could add and remove them. For simplicity, you concatenated a string. Perfectly reasonable choices.
However, I did have a few problems with the structure of the pattern as presented. First of all, I have always believed the type of an object to be highly relevant. In your implmentation, the type of "car" changes as you adorn it with options. Car car = new FerrariSpider();
car = new OptionLeather(car);
car = new OptionAlloyWheels(car);
car = new OptionTurbo(car);
This seems confusing and somewhat arbitrary. If you happened to adorn it in a different order, the car variable would end up as (for example) an "OptionLeather" object.
Also, from a conceptual perspective, to me, an AlloyWheels option is not a kind of (AKO) Car. Wouldn't it have been just as simple and cleaner to have the Car object maintain a list of options that are associated with it? Then the options would not have to be derived from "Car" and therefore not present themselves as AKO Car. They would be derived from Options or something.
Finally, doesn't this implementation rely on the coincidence that an Option and a Car both happen to have Description and Cost? What if you wanted your Car to have "Engine Displacement", "Model Year", "4 Wheel Drive (Boolean)" and "EPA City Mileage" properties? Would you still derive Option from Car?
Maybe I'm just not getting it. I'd be interested in hearing your thoughts on these comments.
Thanks again
Tom Clement Serena Software, Inc. www.serena.com
articles[^]
|
| Sign In·View Thread·PermaLink | 5.00/5 (2 votes) |
|
|
|
 |
|
|
Tom Clement wrote: Also, from a conceptual perspective, to me, an AlloyWheels option is not a kind of (AKO) Car. Wouldn't it have been just as simple and cleaner to have the Car object maintain a list of options that are associated with it? Then the options would not have to be derived from "Car" and therefore not present themselves as AKO Car. They would be derived from Options or something.
If you take a look at the link Charl provided www.dofactory.com/Patterns/PatternDecorator.aspx[^] which provides a very generic diagram and implementation of decorator as well as a "real world" example; you will notice that the pattern relies on the concrete components and the concrete decorators sharing a common type. This is the reason the options are derived from Car.
Tom Clement wrote: Finally, doesn't this implementation rely on the coincidence that an Option and a Car both happen to have Description and Cost? What if you wanted your Car to have "Engine Displacement", "Model Year", "4 Wheel Drive (Boolean)" and "EPA City Mileage" properties? Would you still derive Option from Car?
I wouldn't say that it is coincidence that option and car have description and cost. I think we could do the same with the examples you have provided. For example, "Engine Displacement" in my mind is really a property of maybe "Engine Type" and "Engine Type" would have a description and a cost. The same would be true for "4 Wheel Drive", you are going to pay more for "4 Wheel drive" and so it has a cost associated with it. I would say that "4 Wheel Drive" or "2 Wheel Drive" are better described as "Drive Train". "Model Year" I don't really think of as an option per se and "EPA Mileage" wouldn't be an option either, but perhaps a property of the engine you choose.
Two things to keep in mind about this example, which I should have mentioned in the article itself: 1) When I thought up the example, I was thinking more of a wizard type application where the user starts with a bare car and then picks the options they want to see on it to arrive at the final cost of the car.
2)The purpose of the example was to show how to implement the decorator pattern, not to make the be all end all car creation app. The purpose for the article was to explain what patterns are and why they are useful to those who have no knowledge of patterns. This example is an implementation of decorator. Compare the structure to http://www.dofactory.com/Patterns/PatternDecorator.aspx ( thanks again for providing that Charl) and you should see that they are the same.
Thanks to the comments I have received(all of which I truly appreciate), two things are painful obvious to me: 1) I didn't spend enough time explaining the intent of the example. 2) Some of the issues raised, while valid, are outside of the scope of the proposed application. Again, that's my fault for not explaining the example better in the article. Luckily, it also illustrates the point that, depending on your needs, decorator may not be the way to go. Patterns aren't a silver bullet. Knowing where to apply them is just as important as knowing how to apply them (as the comments I have received point out
Hope this helped some.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Ray,
Your repsonse is very helpful.
I guess my complaint about the type of the object changing is really a complaint about the pattern itself. From what you say, the fact that the type of the class you end up with is arbitrary (reflecting the last option added) is a fundamental characteristic of the pattern itself. I still don't like it, but... what the hey... I don't like fish either.
One last question, pertaining to the Engine Displacement discussion. It seems that since the type of the object you end up with is arbitrary (i.e. the last option added), you can't rely on class specific properties (in the C# sense) to store any option specific information. For example, if engine type is an option that is being adorned, and the last option you add is leather seats, you only have the interface available for leather seats to get engine displacement information. This means that you either have to overload the CAR properties to include things about engine displacement, or you need to provide a generic name/value pair type of property to store such arbitrary information. Am I right here? If so, do you like it? (I don't )
Thanks again. Tom
Tom Clement Serena Software, Inc. www.serena.com
articles[^]
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
This is a good example of how patterns help you to implement solutions. I think it is great to see as many examples of how patterns can be used in your language as possible.
-- modified at 15:47 Wednesday 4th January, 2006
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
To me there just some thing wrong conceptually with the decorator inheriting and encapsulating the decorated object. What is the motivation behind this? Surely an interface is the ideal solution. eg.abstract class Car { IOption[] Options; }
interface IOption { Car Car {get;} int Cost {get;} }
interface IColorOption : IOption { Color Color {get;} }
xacc.ide-0.1.1 released! :) Download and screenshots
|
| Sign In·View Thread·PermaLink | 4.82/5 (4 votes) |
|
|
|
 |
|
|
The decorator pattern is useful under certain conditions and the article certainly helps in understanding what to do to implement them, but it doesn't deal with the most important aspects - HOW and WHEN to use them.
I know you went to a lot of effort to put this out there, but as it stands the article is one I would be very wary of referencing.
Taking the car example, I also have problems with this pattern as you've described it in use. While I normally can look beyond the specifics, many can't, and will consider your example to be the defining problem for decorator use.
Doing it this way how do you remove an option? That is, how do you remove the option cost? How do we remove the encapsulation class once it's created if the user changes their mind? Multiple objects works, but now you're increasing memory use AND we have to track the individual objects introducing complexity. The very situation we wanted to avoid by using a decorator.
Now what about hierarchies - options that need other options? Say, if you have leather, now you can choose between pigskin, oxhide, & suede. This model would need either three mutually exclusive decorator's, or a leather decorator and three more wrapping decorator's plus a whole lot of code around the create instances. The first introduces a data dependency to identify what we're doing a la "if then else" which we obviously wanted to avoid by using a decorator in the first place, and the second - well, there's nothing like peeling an onion to make a developer cry.
Overall, the leppie solution works best for the example.
Nothing is impossible, we just don't know the way of it yet.
|
| Sign In·View Thread·PermaLink | 5.00/5 (2 votes) |
|
|
|
 |
|
|
My goal in writing this was to explain what design patterns were to those unfamiliar with them. I felt like I needed an example to do that effectively. After reading your comments, it would appear that perhaps I didn't choose the best example.
As I mentioned in my article "there are usually several potential solutions to any one problem. However, all solutions are not created equal".
Having said that, I do think this explains patterns and why they are useful and also illustrates how to implement decorator.
Perhaps either of you could suggest a problem better solved with this pattern?
Thanks for the input, I appreciate it.
-- modified at 15:43 Tuesday 3rd January, 2006
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Patterns are cool. The example given, well, allright. Think about what decoration means. There is something that is decorated with something. Something that is decorateable knows whether it is decorated with something. That can be many things but they all can decorate other things. Maybe even something that can decorate something else can be decorated itself indeed. A car and options is a good example to apply such a pattern to. Can you think of one where the decoration is behavioural? Then try to implement these two in a better way.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Damn i have read 1-2 articles about patterns and didnt get it quite well, now with you`r example and by Leppies and Limey`s comments i have made better picture about patterns, now i can better understand more advanced patterns. Thanks guys !
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
| | |