laitimes

Design pattern (15) -- structural pattern _ decoration pattern

author:chencalf

0. Main references

(1) It is better to speak: https://blog.csdn.net/mzl87/article/details/127878302

(2)https://www.cnblogs.com/for-easy-fast/archive/2023/06/05/17458083.html

(3) It's OK too:https://www2014.aspxhtml.com/post-20244/

1. Concept

1.1 Sources of the problem

(1) Subclasses are complex subclasses, and there are so many subclasses.

Design pattern (15) -- structural pattern _ decoration pattern

Image source https://www.bilibili.com/video/BV1Jz4y1d7TX?p=10

1.2 The role of the decorator mode

Decorator mode is designed to dynamically add additional functionality to existing objects. Decorators provide an alternative to subclassing extended functionality. While it is possible to add functionality to an entire object class through subclassing of an object class, the decorator pattern aims to add functionality to only a single object, leaving the rest of the class untouched.

  • (1) It is sometimes commented that the pattern follows the open-closed principle by enhancing an existing type without modifying the original type.
  • (2) It is very interesting that the model achieves its goals by going against the wrong way of the OO recommendations.

1.3 Combination vs. Inheritance Choice?

Typical problems with object-oriented design:

(1) For a given class/object A, how and based on what criteria do you choose between composition and inheritance when creating a new class/object B to reuse class/object A? The usual solution is this: if you intend to reuse an existing Public interface of class A, use inheritance. If you intend to reuse only the functionality of existing Class A, choose Composition.

However, the decorator pattern is the opposite:

It plans to reuse the Public interface of the existing class, but with a composition. This decision has some implications for the issue of the Public interface extension, which we'll see later.

2 Motivation and intent for the use of decorators

2.1 Motivation

Subclasses are complex subclasses, there are so many subclasses, and the functional expansion is becoming more and more complex. The root of the problem described above is that we "overuse inheritance to extend the functionality of objects", which is inflexible due to the static nature that inheritance introduces to types; And as the number of subclasses increases (the number of extended functions increases), the combination of various subclasses (the combination of extended functions) leads to the expansion of more subclasses (multiple inheritance).

How do you make the "Extension of Object Functionality" dynamically implemented as needed? And at the same time avoid the problem of subclass bloat caused by the "increase in extended functions"? Thus minimizing the impact of any "feature expansion changes"?

2.2 Intent

Dynamically add some extra responsibilities to an object. In terms of adding functionality, the Decorator pattern is more flexible than generating subclasses. (Design Patterns GoF)

2.3 Uses

  • During software development, it is not uncommon to encounter situations where you need to add some extra behavior to an object. If you modify the code of this object directly, it may cause instability in other code, and it will lead to poor maintainability of the code. This is where the decorator pattern comes into play.
  • Using the decorator pattern, you can dynamically add some extra responsibilities to an object at runtime without having to modify the object's code. This way, you can maintain the stability and maintainability of your old code, while still being able to meet new requirements.

3 Implementation of decorators

3.1 Composition of the Decorator Pattern

The implementation of the decorator pattern requires the following steps:

  • (1) Define an interface (or abstract component) that contains the methods that need to be implemented for both the decorated object and the decorator object.
  • (2) Implement a specific class that implements the interface and contains some basic behavior.
  • (3) Implement a decorator class (which is an abstract class) that also implements the interface and includes a reference to the decorated object.
  • (4) In the decorator class, implement the additional behaviors that need to be added, and when you call the method of the decorated object, the corresponding method is also called.
  • (5) In the client-side code, create a concrete object and dynamically add some extra behavior to it with the decorator class.

3.2 Structural diagram of the decorator

(1)

Design pattern (15) -- structural pattern _ decoration pattern

(2)

Design pattern (15) -- structural pattern _ decoration pattern

3.3 Test examples

Refer to https://www.cnblogs.com/for-easy-fast/archive/2023/06/05/17458083.html

(1) Define an interface

For example, define a class of shapes

// Component 接口
public interface IShape
{
    void Draw();
}           

(2) Define a specific class that implements the above interface

For example, define the implementation of a rectangular class

// ConcreteComponent 类
public class Rectangle : IShape
{
    public void Draw()
    {
        Console.WriteLine("Drawing a rectangle.");
    }
}           

(3) Define the decoration class and implement the above interface

Note:

  • inherited the interface,
  • The class contains the interface field of the protected attribute
  • Use the virtual function virtual to implement the methods in the interface. (If the interface is defined using an abstract class, it can be overridden and implemented using the same method)
// Decorator 类
public abstract class ShapeDecorator : IShape
{
    protected IShape decoratedShape;

    public ShapeDecorator(IShape decoratedShape)
    {
        this.decoratedShape = decoratedShape;
    }
    public virtual void Draw()
    {
        decoratedShape.Draw();
    }
}           

(4) Define two specific classes and expand their respective functions

//(4) ConcreteDecorator 类1
public class RedShapeDecorator : ShapeDecorator
{
    public RedShapeDecorator(IShape decoratedShape) : base(decoratedShape)
    {
    }

    public override void Draw()
    {
        decoratedShape.Draw();
       //具体功能扩展测试代码如下
        Console.WriteLine("Border Color: Red_1");
    }
}
//(5) ConcreteDecorator 类2
public class BlueShapeDecorator : ShapeDecorator
{
    public BlueShapeDecorator(IShape decoratedShape) : base(decoratedShape)
    {
    }

    public override void Draw()
    {
        decoratedShape.Draw();
      //具体功能扩展测试代码如下
        Console.WriteLine("Border Color: blue2_1");
    }
}
           

(5) Test code for the client

// 客户端代码
public class Client
{
    public void run()
    {
        // (1)创建一个具体的对象
        IShape rectangle = new Rectangle();

        // (2)用装饰器类动态地给它添加一些额外的行为
        IShape redRectangle = new RedShapeDecorator(rectangle);

        // (3)原始具体类的输出
        rectangle.Draw(); 
        Console.WriteLine("-----------------------------");
        // (4)用具体类装饰一下输出
        redRectangle.Draw();
        Console.WriteLine("-----------------------------");

        // (5)注意啦,对上面的装饰器结果接着进行装饰!!!
        IShape blueShapeDecorator = new BlueShapeDecorator(redRectangle);
        blueShapeDecorator.Draw();
    }
}

public class Demo
{
    static void Main(string[] args)
    {
        Client client = new Client();
        client.run();
    }

}           

(6) Test results

Design pattern (15) -- structural pattern _ decoration pattern

4. Relevant processes and attention to implementation

(1) The interface (abstract class) defines the specification

(2) Concrete class A implements the basic function

(3) The decorator (abstract class) implements the interface and defines the interface field of protected

(4) The specific class of the decorator expands the interface function

(5) the client creates a concrete class A; In the decorator concrete class A, and in the constructor the concrete class A is passed; This expands the extended functionality of specific class A

(6) The client can also create a decorator concrete class B, and pass the decorator concrete class A in the constructor, and then extend the decorator A, so as to achieve two extended functions

(7) The decorator can be decorated all the way.

Read on