A Decorator class is a class that extends the functionality of another class at run-time without inheriting it : is one of the 23 software patterns researched by the Gang of Four in their 1995 classic book. The Decorator Pattern become really useful in an MVC application, when you want to add functionality to many classes , respecting the Open-Closed Software Principle, therefore without touching any existing code.
The Open-Closed Principle, stated by Meyer in 1988, specifies that any class once completed, could only be modified in order to fix errors, but any new or appended functionality would require an extension new class to be created.This pattern allows you to create absolutely loosely-coupled relationships between classes, since it works without the standard inheritance mechanism known as "sub-classing" : instead of extending functionality at compile time through a sub-class, the Decorator wraps another objects at a runtime dynamic basis.
This pattern is materialized using interfaces or abstract classes. In this example, we'll use an abstract class, because it will be preferable in real world applications (see this article comparing interfaces vs abstract classes).
The following lines contain the code for the Decorator. Just use it as a bootstrap in your Model's classes :
Suppose you have this given parent-child classes to be extended with a Decorator:
abstract class Parent
{
public abstract void DoIt();
}
class Child : Parent
{
public override void DoIt()
{
Console.WriteLine("You are at Child .DoIt()");
}
}
And when called, the output will be :
Child child = new Child();
child.DoIt();
child.DoIt();
You are at Child .DoIt()
Step #1 : Create an abstract Decorator class:
abstract class DecoratorBase : Parent
{
protected Parent component;
public void Setup(Parent component)
{
this.component = component;
}
public override void DoIt()
{
if (component != null)
{
component.DoIt();
}
}
}
{
protected Parent component;
public void Setup(Parent component)
{
this.component = component;
}
public override void DoIt()
{
if (component != null)
{
component.DoIt();
}
}
}
The abstract base decorator wraps the old class as a component, and overrides the methods to extend , simultaneously respecting the old functionality.
Step #2 : Create as many Decorators as you wish :
class Decorator1 : DecoratorBase
{
public override void DoIt()
{
base.DoIt();
ExtendedFunctionality();
Console.WriteLine("You are at Decorator1 .DoIt()");
}
void ExtendedFunctionality()
{
// TODO
}
}
The functional decorator does two things:
}
}
The functional decorator does two things:
1) calls the method's base of the old class (through the abstract decorator)
2) adds new behavior to the old functionality
Thus , the old class is now a component of the decorator.
Call & output:
Child child = new Child();
Decorator1 dec1 = new Decorator1 ();
dec1.Setup(child);
dec1.DoIt();
Yet another Decorator :
Decorator1 dec1 = new Decorator1 ();
dec1.Setup(child);
dec1.DoIt();
You are at Child.DoIt()
You are at Decorator1 .DoIt()
Yet another Decorator :
class Decorator2 : DecoratorBase
{
public override void DoIt()
{
base.DoIt();
ExtendedFunctionality();
Console.WriteLine("You are at Decorator2 .DoIt()");
}
void ExtendedFunctionality()
{
{
public override void DoIt()
{
base.DoIt();
ExtendedFunctionality();
Console.WriteLine("You are at Decorator2 .DoIt()");
}
void ExtendedFunctionality()
{
// TODO
}
}
}
}
Call and output:
Child child = new Child();
Decorator1 dec1 = new Decorator1 ();Decorator2 dec2 = new Decorator2 ();
dec1.Setup(child);
dec2.Setup(dec1);
dec2.DoIt();
You are at Child.DoIt()
You are at Decorator1.DoIt()
You are at Decorator2 .DoIt()
That means, with this design pattern we can not just decorate twice an old class, but also decorate another decorator, which now becomes a component of a newer decorator class.
Important:
We practically didn't touch the old code : the old class is now a component of the new decorator/s.
All we did was adding an abstract parent to the extended class, thus respecting the Open-Close Principle.
That's all!!
Happy programming.....
By Carmel Schvartzman
כתב: כרמל שוורצמן
No comments:
Post a Comment