I'm already the new Microsoft Live Writer to post to my personal blog, so I thought I'd try it out with my MSDN blog as well. Just to make it interesting, I thought I'd add a quick little post about the decorator pattern.
The decorator pattern is a Gang of Four (GOF) pattern that allows you to add behavior or state to an existing component without modifying the original component.
I've created a code example, and created a class diagram (in Text) to show the structure here.
I have defined an abstract class "BaseComponent" that does some work. It has exactly one method called DoWork. I then created a concrete component called WalkingComponent that inherits the Base Component and overrides the abstract method.
At this point we have a working program, but we want to add new functionality. Here's where the fun begins.
We can create another inheritor of BaseComponent that knows it's a decorator. the code for the Decorator class is below.
abstract class Decorator : BaseComponent { protected BaseComponent component; public Decorator(BaseComponent component) { this.component = component; } public override void DoWork() { if (null != component) { component.DoWork(); } } }
The decorator class contains a field of the BaseComponent type. It wraps the functionality of that class (some or all methods). In it's override of DoWork, it first checks to see if it's component is null, then calls the components DoWork method. We've just successfully created an Abstract decorator for the BaseComponent.
Next we'll add a decorator with state. This is a very trivial example. Here's the code. We've added a property called NewState to hold a string value that we can read later if we need to. Here's the code.
class DecoratorWithState : Decorator { public DecoratorWithState(BaseComponent component) : base(component) { } private string newState; public string NewState { get { return newState; } } public override void DoWork() { base.DoWork(); newState = "Windows Mobile Phone"; Console.WriteLine("I've brought my {0} with me.", newState); } }
Whew, that was easy...
Now we're going to add some behavior with a new class called DecoratorWithAddedBehavior. Here's the code.
class DecoratorWithAddedBehavior : Decorator { public DecoratorWithAddedBehavior(BaseComponent component) : base(component) { } public override void DoWork() { base.DoWork(); DoAdditionalWork(); Console.WriteLine("I'm finished. I'm headed home."); } void DoAdditionalWork() { if (component is DecoratorWithState) { DecoratorWithState stateful = (DecoratorWithState)component; Console.WriteLine("I have email on my {0}. I'm stopping to read it.", stateful.NewState); } else Console.WriteLine("I'm tired, think I'll take a break."); } }
Ok, this one gets a little tricky, because I'm trying to get tricky. I'm mixing concepts here, and probably shouldn't but it's my post, and I can do as I please... :-)
I've added the DoAdditonalWork method to my class. When a caller calls my DoWork method, they will still call down the chain of components, execute each one, but I've injected my new method here to in this case "take a break". If the component passed to me is a DecoratorWithState, I'm going to use some of that state. If not, I'm just going to do a simple Console.WriteLine().
Anyway, to run this sample, we're going to use a few factory methods, that will create our component stacks for us. Here's the "Program" class code.
class Program { static void Main() { // basic funtionality BaseComponent decorator = GetMyBaseComponent(); Console.WriteLine("Concrete Component"); decorator.DoWork(); Console.WriteLine(); // added some state decorator = GetStatefulComponent(); Console.WriteLine("Stateful Component"); decorator.DoWork(); Console.WriteLine(); // added some additional behavior decorator = GetAddedBehaviorComponent(); Console.WriteLine("Added Behavior Component"); decorator.DoWork(); Console.WriteLine(); Console.ReadLine(); } // factory methods static BaseComponent GetMyBaseComponent() { WalkingComponent component = new WalkingComponent(); return component; } // factory method (could easily be an abstract factory, but thats a whole other article. static BaseComponent GetStatefulComponent() { return new DecoratorWithState(GetMyBaseComponent()); } // factory method (could easily be an abstract factory, but thats a whole other article. static BaseComponent GetAddedBehaviorComponent() { return new DecoratorWithAddedBehavior(GetStatefulComponent()); } }
Ok, that's just about it. The last thing to do is show the output of this excercise...