Decorator (Decorator pattern)

A Decorator is a structural pattern, a design pattern that extends the additional functionality of an object, alias Wrapper.

Intent: To dynamically add some additional responsibilities to an object. The Decorator pattern is more flexible in terms of adding functionality than subclassing.

For example,

If you don’t understand the above description, it doesn’t matter. Design patterns need to be used in daily work. Examples will help you understand better.

Photo frame

Photo + photo frame = photo with photo frame, which is a decorative mode behind: Photos have the function of looking, and photo frame has the function of decoration. On the basis of looking at photos, you can also see the carefully designed photo frame, which increases the aesthetic feeling. At the same time, photo frame can also increase the preservation time and security of photos.

Photo frame and photo are a combination relationship, any photo can be put into the picture frame, rather than each photo to generate a specific picture frame, obviously, the combination method is more flexible.

File read and write with cache

Suppose we have a class called FileIO that reads and writes files but has no caching capability. Is it better to subclass CachedFileIO or create CachedIO?

At first glance it might seem like CachedFileIO is easier to use and CachedIO is a bit more cumbersome to use, but what if we added a network read-write class NetworkIO and a database read-write class DBIO?

Obviously, inheritance can cause the number of subclasses to grow rapidly, but composition can be very flexible. You just need new CachedIO(new NetworkIO()) to create a cache-enabled network reader.

Of course, in order to achieve this capability, CachedIO needs to inherit from the same class and have the same interface as FileIO, CachedFileIO, and CachedIO.

Build the platform component Wrapper

The wrapper pattern is also known as wrapper. Wrapper is also commonly encountered in front-end scaffolding scenarios. When the scaffolding platform loads a component and wants to extend its basic capabilities, the wrapper layer is used to nest the component. Enhance third-party components.

Intention to explain

Intent: To dynamically add some additional responsibilities to an object. The Decorator pattern is more flexible in terms of adding functionality than subclassing.

Unlike inheritance, composition can be done at run time, so it’s called “dynamic addition,” where “extra responsibility” refers to everything from printing some log when a button is clicked to drawing an extra scroll bar and border when a text box is drawn.

The implication of the statement “Decorator pattern is more flexible than subclassing in terms of adding functionality” is that composition is more flexible than inheritance, which produces a large number of subclasses when there is a lot of extensibility, whereas composition, which can write handlers in advance and construct them dynamically when needed, is obviously more flexible.

chart

ConcreteComponent ConcreteComponent refers to a Component that needs to be decorated. As you can see, the Decorator inherits from the same class as the Decorator, ensuring that the API is consistent and that no matter how many layers are decorated, the Decorator always conforms to the Component type.

ConcreteDecoratorA and ConcreteDecoratorB implement each of them. If there is only one Decorator, the Decorator can degenerate into an implementation in itself.

The code example

The following example is written in typescript.

class Component {

  // Have click events

  public onClick = (a)= > {}

}



class Decorator extends Component {

  private _component



  constructor(component) {

    this._component = component

  }



  public onClick = (a)= > {

    log('dot')

    this._component.onClick()

  }

}



const component = new Component()

// A normal click

component.onClick()



const wrapperComponent = new Decorator(component)

// a single click with the dot function

wrapperComponent.onClick()

Copy the code

The way to do this is very simple. By combining, we get a more powerful component by using constructors to hold component instances and adding enhanced implementations when we overwrite functions.

disadvantages

The problem with decorators is also a combinatorial problem, too many combinations can result in:

  • The complexity of the composition process, to generate too many objects.
  • As more layers of wrappers increase debugging costs, it is difficult to trace which layer of wrappers caused a bug.

conclusion

The Decorator pattern is a very common pattern. The Decorator is a transparent wrapper, and as long as the wrapper is transparent, you can maximize the benefits of the Decorator pattern.

Finally, summarize a decorator application diagram:

Close reading design Patterns – Decorator Decorator patterns · Issue #286 · dT-fe /weekly

If you’d like to participate in the discussion, pleaseClick here to, with a new theme every week, released on weekends or Mondays. Front end Intensive Reading – Helps you filter the right content.

Pay attention to the front end of intensive reading wechat public account

Copyright Notice: Freely reproduced – Non-commercial – Non-derivative – Remain signed (Creative Commons 3.0 License)