Decorator pattern mainly solves the problem that inheritance relationship is too complicated, and replaces inheritance by composition. Its main function is to add enhancements to the original class. The decorator class inherits from the same parent class as the original class, which feels like the proxy pattern. The decorator mode is used to add functionality, while the proxy mode is used to add functionality unrelated to the original class.

In this paper, a UML class diagram link is: www.processon.com/view/link/6…

This article is linked to: github.com/shidawuhen/…

Definition 1.

1.1 Decorator mode

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

UML class diagram:

1.2 analysis

The first thing we need to understand is, why is composition better than inheritance?

  • Inheritance has many functions, but if inheritance is too deep and complex, it will affect the maintainability of code.

  • Inheritance has three main functions: representing IS-A relationships, supporting polymorphic characteristics, and code reuse. These three functions can be achieved by combination, interface and delegation. In addition, using composition can also solve the problem of code maintainability caused by too deep and complex inheritance relationship.

Again, look at the difference between the decorator pattern and the proxy pattern.

  • At the UML level, there are no subclasses under Proxy, but there are subclasses under Decorator. A Proxy and a Decorator do some of the same things in that they both need to package the functions of the original class, but the Proxy adds some functionality that is not related to the original class. The main purpose of the Proxy package is to make the ConcreteDecorator less repetitive and focus only on the functions that need to be added.

  • At the usage level, Proxy is straightforward, with the client calling the Proxy and the Proxy calling the original class. Decorator mode can be nested, A decorates B, B decorates C, and C decorates D.

Now, you might ask, where is the combinatorial action? Let’s think of a scenario where a class Base has a function that encapsulates well, but needs to be strengthened if it wants to use it. This class is D1, and if you use inheritance, you need to override it and call the Base class. If you want to use D1 elsewhere, you need to strengthen some of the functionality. This class is D2, and if you use inheritance, you need to overload and call the base class. This makes inheritance too deep and complex, and then is inheritance necessary? If you think about it, instead of inheritance, you can not only achieve your goals, but also reduce the workload, and remove the shackles of inheritance.

2. Application scenarios

Decorator mode is generally good for encapsulating base class functionality, but requires enhancements that are required by other enhancements.

Lord of War starring Nicolas Cage, I don’t know if you’ve seen it. Remember the scene in which Cage bought a helicopter gunship, then the FBI led the arrest, cage separated the helicopter from the missile is legal. Helicopters are particularly well-packaged and can fly long distances. You want a gunship, you put missiles on it. If you want a medevac, put a doctor on it. You want an arMED-rescue helicopter, you put missiles and doctors on it.

So let’s just code this example.

3. Code implementation

package main import "fmt" /** * @Description: Type Aircraft interface {fly() landing()} /** * @description: Helicopters, */ type Helicopter struct {} func (h *Helicopter) fly() {FMT.Println(" I am a normal Helicopter ")} func (h *Helicopter) Landing () {FMT.Println(" I have a landing function ")} /** * @description: Type WeaponAircraft struct {Aircraft} /** * @Description: @ Receiver a */ func (a *WeaponAircraft) fly() {a.aircraft. Fly () fmt.println (" weaponship ")} /** * */ type RescueAircraft struct {Aircraft} /** * @description: - Added rescue functions to helicopters * @Receiver r */ func (r *RescueAircraft) fly() {r.arcraft. Fly () fmt.println (" Added rescue functions ")} func main() { // Helicopter FMT.Println("------------ helicopter ") := & helicopter {} fly.fly () landing() // helicopter gunship Println("------------ armed helicopter ") weaponAircraft := & weaponAircraft {Aircraft: helicopter, } missile Aircraft. Fly () // fdt.println ("------------ rescue helicopter ") rescueAircraft := & rescueAircraft {Aircraft: helicopter, } rescueAircraft. Fly () // Armed rescue helicopter FMT.Println("------------ armed rescue helicopter ") weaponRescueAircraft := & rescueAircraft {Aircraft: weaponAircraft, } weaponRescueAircraft.fly() }Copy the code

Output:

➜ myproject go run main.go

———— Ordinary helicopter

I’m a regular helicopter

I have a landing function

———— gunship

I’m a regular helicopter

Increased arming

———— Rescue helicopter

I’m a regular helicopter

Added rescue function

———— armed rescue helicopter

I’m a regular helicopter

Increased arming

Added rescue function

There is no Decorator class in the code implementation, mainly because of the nature of the Go combination. Decorators exist because they contain component member variables. Function implementations in Decorators are functions that call Component, so the Decorator needs to be wrapped around each function in Component. But the Go combination does this automatically without encapsulation, which naturally eliminates the need for decorators.

conclusion

Decorator pattern is relatively simple to understand and use. It mainly realizes reuse capability through combination. If the combination variable is interface or base class, series function can be realized.

In use, first of all, we need to make sure that the reusable function is abstractly good, so as not to find that many enhanced functions can be converged. Second, determine if there are cases where enhanced functionality needs to be connected in series, and if so, using decorator mode is appropriate.

Decorator mode embodies the open and close principle, Richter substitution principle and dependency inversion principle.

The last

If you like my article, you can follow my public account (Programmer Malatang)

My personal blog is shidawuhen.github. IO /

Review of previous articles:

recruitment

  1. Bytes to beat | push big 24:00

  2. Bytes to beat | headlines today guangzhou server push r&d engineers

  3. Bytes to beat | trill electricity now hiring front-end development project in Shanghai

  4. Bytes to beat | trill electricity senior server-side development engineer – trading in Shanghai

  5. Bytes to beat | trill electric ShangWuHan server-side development engineer (senior)

  6. Bytes to beat | fly book big customer push product manager

  7. Bytes to beat | trill electricity service side technical posts vacant

  8. Bytedance recruitment special

Design patterns

  1. No more fear of not getting Gin request data

  2. Go Design Mode (12)- Bridge mode

  3. Go Design Pattern (11)- Proxy pattern

  4. Go Design Mode (10)- Prototype mode

  5. Go Design Mode (9)- Builder mode

  6. Go Design Pattern (8)- Abstract Factory

  7. Go Design Mode (7)- Factory Mode

  8. Go Design Pattern (6)- Singleton pattern

  9. Go Design Pattern (5)- Class diagram symbolic representation

  10. Go Design Pattern (4)- Code writing optimization

  11. Go Design Pattern (4)- Code writing

  12. Go Design Patterns (3)- Design principles

  13. Go Design Pattern (2)- Object-oriented analysis and design

  14. Go Design Pattern (1)- Syntax

language

  1. Understand pprof

  2. Go tool generate

  3. Go singleton implementation scheme

  4. Implementation principle of Go channel

  5. Implementation principle of Go timer

  6. Beego framework use

  7. Golang source BUG tracking

  8. Gin framework concise version

  9. Gin source code analysis

architecture

  1. The paging check pit is designed

  2. Payment access general issues

  3. Current limiting 2

  4. Seconds kill system

  5. Distributed systems and consistency protocols

  6. Service framework and registry for microservices

  7. Discussion on Micro-service

  8. Current limiting implementation 1

  9. CDN request process details

  10. Common Cache tips

  11. How to effectively connect with third-party payment

  12. Algorithm is summarized

storage

  1. MySQL development specification

  2. Redis implements distributed locking

  3. The implementation principle of atomicity, consistency and persistence of transactions

  4. InnoDB locks and transactions

network

  1. HTTP2.0 basics tutorial

  2. HTTPS Configuration Combat

  3. HTTPS Connection Process

  4. TCP Performance Optimization

tool

  1. GoLand Practical skills

  2. Automatically generate go struct from mysql table

  3. Markdown editor recommends – Typora

Reading notes

  1. Selected by MAO

  2. The principle of

  3. History As A Mirror

  4. Agile revolution

  5. How to exercise your memory

  6. Simple Logic – After reading

  7. Hot Wind – After reading

  8. Analects of Confucius – After reading

  9. Sun Tzu’s Art of War – Reflections from reading

thinking

  1. Struggle to mobilize all forces for victory

  2. Anti-liberalism

  3. practical

  4. The standard by which you judge yourself

  5. Service team holiday shift plan

  6. Project process management

  7. Some thoughts on project management

  8. Some thoughts on product manager

  9. Thinking about programmer career development

  10. Thinking about code review