Decorator
Add some new features to the object dynamically, it is more flexible than the inheritance, the original component doesn't need to have plenty of functions at the first time, but has only very frequent operations. The decorator is designed to add any other additional operations to the original component if necessary. The decorator pattern makes the high level class simple and decouples the system.
When we use this pattern
- as i said above, if you want to add new features or operations dynamically
- if the original component is hard to inherit
- if the orininal component got lots of combinations in the future, if you use the inheritance mechanism, you have to implement lots of sub-classes. so the decorator is a better option.
- another situation is if you want to add some new operations to the exsiting class, it is better to use this pattern without change the exsiting class
Roles in this pattern
- Component: define some interface
- ConcreteComonent: implement the Component, have the real operation
- Decorator: maintain a reference of the Component and also implement the Component by inheritance
- ConcreteDecorator: implement the Decorator, the very class to decorate the Component.
More descriptions
What the decorator really does is to call the Component's interface and after that do some more operation or change some states, that is the reason why we call it decorator.
Dynamic and flexible are the key words for this pattern, it is the client that decides the order of the decoration and decides how to decorate.
The very component does not need to implement all the potential operations but only the very frequent ones. The potential operations can be implenented by the decorator, you can make as many different concrete decorators as you want for different requirement.
what's more , the different decorators can be used together to decorate the component by the orders you want. compared with the inheritance by the sub-classes, you cannot use them together for the different orders, you got to implement the different ones just beacause of the order requirment.
The decorator is used in very certain time and very certain situation, so you can implement it and leave it there, when it is necessary, use it, which simplifies the original Component.
a small demo is designed to demonstate the above, see below:
namespace Decorator { public abstract class Component { public abstract void Operation(); } public class ConcreteComponent : Component { public override void Operation() { Console.WriteLine("ConcreteComponent"); } } public abstract class Decorator : Component { protected Component component; public void SetComponent(Component component) { this.component = component; } public override void Operation() { if (component != null) { component.Operation(); } } } public class ConcreteDecoratorA : Decorator { private string addedStatus; public override void Operation() { base.Operation(); addedStatus = "New Status"; Console.WriteLine("ConcreteDecoratorA"); } } public class ConcreteDecoratorB : Decorator { public override void Operation() { base.Operation(); AddOperation(); Console.WriteLine("ConcreteDecoratorB"); } private void AddOperation() { Console.WriteLine("New Operation in ConcretedecoratorB"); } } class Program { static void Main(string[] args) { ConcreteComponent c = new ConcreteComponent(); ConcreteDecoratorA d1 = new ConcreteDecoratorA(); ConcreteDecoratorB d2 = new ConcreteDecoratorB(); d1.SetComponent(c); d2.SetComponent(d1); d2.Operation(); } } }