DESIGN PATTERNS FOR EXTENSIBILITY : DECORATOR PATTERN

In the previous post, I discussed about the need for “extensibility” and introduced “Strategy Pattern”. In this post, let me introduce you “Decorator Pattern” (aka Wrapper) and discuss it.

Image result for pakistan truck decorations

Whenever I hear about word “Decoration” – Pakistani Trucks and Three-shaws come to my mind as they were decorated in every possible way.

Unlike Strategy Pattern, Decorator Pattern is a “Structural Pattern” – which by identifying relationships, simplifies the structure. This focus on how the classes are composed from other classes and inherit from each other. Or in simple words “Structure Pattern, ease the design by identifying a simple way to realize relationships between entities”. As it is named, “Decorator Pattern” attach open-ended accessory responsibilities to an object dynamically. The Decorator Pattern uses composite reuse principle to extend the functionality of an object at run-time.

DecoratorClassDiag1



// The base interface
public interface IVehicle
{
	void Drive();
}

// Concrete Object - which is supposed to be modified during runtime.
public class Car : IVehicle
{
	public void Drive()
	{
		Console.Write("Car");
	}
}







// Decorator 1
public abstract class DrivingModeDecorator : IVehicle
{
	private IVehicle vehicle;

	public DrivingModeDecorator(IVehicle vehicle)
	{
		this.vehicle = vehicle;
	}
	

	public virtual void Drive()
	{
		Console.Write(" driving ");
		this.vehicle.Drive();
	}
}


// Decorated Object for self driving according to Decorator 1
public class SelfDrivingCar : DrivingModeDecorator
{
	public SelfDrivingCar(IVehicle vehicle) : base(vehicle) { }

	public override void Drive()
	{
		Console.Write(" self ");
		base.Drive();
	}
}






// Decorator 2
public abstract class WheelsDecorator : IVehicle
{
	private IVehicle vehicle;
	public WheelsDecorator(IVehicle vehicle)
	{
		this.vehicle = vehicle;
	}

	public virtual void Drive()
	{
		Console.Write(" wheel ");
		this.vehicle.Drive();
	}
}


// 4 Wheel Decorated Object according to Decorator 2
public class FourWheelDriveCar : WheelsDecorator
{
	public FourWheelDriveCar(IVehicle vehicle) : base(vehicle) { }

	public override void Drive()
	{
		Console.Write(" Four ");
		base.Drive();
	}
}


// 2 Wheel Decorated Object according to Decorator 2
public class TwoWheelDriveCar : WheelsDecorator
{
	public TwoWheelDriveCar(IVehicle vehicle) : base(vehicle) { }

	public override void Drive()
	{
		Console.Write(" Two ");
		base.Drive();
	}
}

Now in your client class,

Car car = new Car();

SelfDrivingCar selfdrivingCar = new SelfDrivingCar(car);
FourWheelDriveCar fourWheelSelfDriveCar = new FourWheelDriveCar(selfdrivingCar);
fourWheelSelfDriveCar.Drive();

or even,

Car car = new Car();
TwoWheelDriveCar twoWheelDriveCar = new TwoWheelDriveCar (car);
twoWheelDriveCar .Drive();

So, if you look at the instance where we are using ‘fourWheelSelfDriveCar’, there we are first creating a Car object and decorate it as a SelfDrivingCar, later which is decorated as a FourWheelDriveCar. So, now the final object is a “Four wheel self driving car”

or, why not we use the below instead,

FourWheelDriveCar fourWheelSelfDriveCar = new FourWheelDriveCar(new SelfDrivingCar(new Car()));

In the second instance, we are just decorating another new Car as a TwoWheelDriveCar. So in case, in the future if you need to add a “semi-autonomous car” – you just need to add a decorator to the DrivingModeDecorator. Or you can even introduce a new Fuel type decorator.

Since this is open for extensions, this satisfies “Open-Closed Principle” and since this has a strong sub-typing, this satisfies “Liskov Substitution Principle” as well.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s