Decorator Pattern
The decorator pattern is a structural pattern that dynamically extends the functionality of an object without changing the original class file or using inheritance.
The decorator pattern creates a wrapper, that is, a wrapper around a real object.
role
1. Abstract Component
An abstract interface is given to standardize objects ready to receive additional responsibilities.
2. Concrete Component
Define a class that will receive additional responsibilities;
3. Abstract Decorator
Holds an instance of a Component object and implements an interface consistent with the abstract Component interface.
4. Concrete Decorator
Responsible for adding additional responsibilities to the component objects.
The sample
The namespace DecoratorPattern contains the Car class, Maserati Class, Ferrari Fabbrica class, CoolCar class, Car sticker Paster class, and Car Visor class. This example gives a simple exterior decoration to the car using decorator mode.
public abstract class Car {
public string Name { get; set; }
public abstract void StartUp();
}
Copy the code
The Car base class, Car, acts as an abstraction.
public class Fabbrica : Car {
public Fabbrica() {
Name = "Fabbrica";
}
public override void StartUp() {
Console.WriteLine($"{Name} is starting!"); }}Copy the code
The Ferrari Fabbrica class acts as a concrete artifact.
public class Maserati : Car {
public Maserati() {
Name = "Maserati";
}
public override void StartUp() {
Console.WriteLine($"{Name} is starting!"); }}Copy the code
The Maserati class acts as a concrete building block.
public abstract class CoolCar : Car {
protected Car _car = null;
public CoolCar(Car car) {
_car = car;
}
public override void StartUp() {
Console.WriteLine($"{_car.Name} is starting!"); }}Copy the code
The CoolCar class acts as an abstract decoration.
public class Paster : CoolCar {
public Paster(Car car) : base(car){}public override void StartUp() {
SetPaster();
base.StartUp();
}
private void SetPaster() {
Console.WriteLine($"Set paster to {_car.Name}!"); }}Copy the code
The Paster class, which inherits the CoolCar class, makes it possible to decorate cars.
public class Visor : CoolCar {
public Visor(Car car) : base(car){}public override void StartUp() {
SetVisor();
base.StartUp();
}
private void SetVisor() {
Console.WriteLine($"Set visor to {_car.Name}!"); }}Copy the code
The car Visor class, by inheriting the CoolCar class, provides the possibility to decorate the car.
public class Program {
private const string LINE_SPLIT = "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --";
private static Car _car = null;
private static CoolCar _coolCar = null;
public static void Main(string[] args) {
_car = new Maserati();
_coolCar = new Visor(_car);
_coolCar.StartUp();
Console.WriteLine(LINE_SPLIT);
_car = new Fabbrica();
_coolCar = newPaster(_car); _coolCar.StartUp(); Console.WriteLine(LINE_SPLIT); Console.ReadKey(); }}Copy the code
This is the caller’s code, and here is the output of the case:
Set visor to Maserati!
Maserati is starting!
-------------------------
Set paster to Fabbrica!
Fabbrica is starting!
-------------------------
Copy the code
advantages
1. The decorator pattern and inheritance are both intended to extend the functionality of objects, but the decorator pattern can provide more flexibility than inheritance. 2. By using different concrete decorator classes and permutations of these decorator classes, developers can create many combinations of different behaviors.
disadvantages
1. This more flexible nature than inheritance also means more complexity; 2. Decoration mode leads to many small classes in your design, which can complicate your application if overused. Decorator mode is designed for abstract Component types. However, if you are programming for specific components, you should rethink your application architecture and the appropriateness of decorators. You could also change the Component interface to add new exposed behaviors and implement a “translucent” decorator pattern. Make the best choice in the actual project.
Usage scenarios
Need to extend the functionality of a class, or add additional responsibilities to a class; 2. You need to add functions to an object dynamically, and these functions can be undone dynamically. 3. A very large number of functions need to be added by permutations and combinations of some basic functions, so that the inheritance relationship becomes unrealistic; 4. When the method of generating subclasses cannot be used for expansion. In one case, there could be so many independent extensions that the number of subclasses to support each combination would explode. Another case might be because the class definition is hidden, or the class definition cannot be used to generate subclasses.