O Decorator Pattern é um padrão de design estrutural que permite adicionar novos comportamentos e responsabilidades a objetos dinamicamente sem modificar objetos existentes. Esse padrão alcança aprimoramento funcional combinando objetos envolvendo-os em objetos decoradores.
Explicação do princípio:
O modo de decoração cria uma classe decorator que implementa a mesma interface do objeto decorado e mantém uma referência ao objeto decorado. Uma classe decorator estende a funcionalidade do objeto decorado executando um comportamento adicional antes ou depois de invocar o método do objeto decorado. Essa abordagem possibilita adicionar, remover ou alterar dinamicamente a funcionalidade de um objeto em tempo de execução.
Diagrama de estrutura subjacente:
O seguinte é um diagrama de estrutura clássico do modo de decoração:
+------------------+
| Component |
+------------------+
| operation() |
+------------------+
/ \
/ \
+----------------+ +----------------+
| Concrete | | Concrete |
| Component | | Component |
+----------------+ +----------------+
| operation() | | operation() |
+----------------+ +----------------+
/ \
/ \
+----------------+ +----------------+
| Decorator | | Decorator |
+----------------+ +----------------+
| component | | component |
+----------------+ +----------------+
| operation() | | operation() |
+----------------+ +----------------+
No diagrama de estrutura acima, Component
é uma classe ou interface abstrata que define as operações básicas. Concrete Component
É uma classe de implementação concreta que fornece funções básicas. Decorator
é uma classe abstrata para decoradores que também implementa Component
a interface e mantém Component
uma referência a um objeto. Concrete Decorator
É uma classe de implementação de decorador concreto, que aprimora o objeto decorado estendendo a função do decorador.
Aqui está um exemplo de código implementando o padrão decorador em Go:
package main
import "fmt"
// Component 接口定义了基本操作
type Component interface {
Operation()
}
// ConcreteComponent 是具体的组件实现
type ConcreteComponent struct{}
func (c *ConcreteComponent) Operation() {
fmt.Println("执行基本操作")
}
// Decorator 是装饰器抽象类
type Decorator interface {
Component
}
// ConcreteDecoratorA 是具体的装饰器实现类
type ConcreteDecoratorA struct {
component Component
}
func (d *ConcreteDecoratorA) Operation() {
fmt.Println("执行装饰器A的操作")
d.component.Operation()
}
// ConcreteDecoratorB 是具体的装饰器实现类
type ConcreteDecoratorB struct {
component Component
}
func (d *ConcreteDecoratorB) Operation() {
fmt.Println("执行装饰器B的操作")
d.component.Operation()
}
func main() {
// 创建具体组件对象
component := &ConcreteComponent{}
// 创建装饰器A,并将组件对象作为参数传入
decoratorA := &ConcreteDecoratorA{
component: component,
}
// 创建装饰器B,并将装饰器A作为参数传入
decoratorB := &ConcreteDecoratorB{
component: decoratorA,
}
// 调用装饰器B的操作
decoratorB.Operation()
}
No código acima, Component
é a interface que define a operação básica e ConcreteComponent
é a implementação do componente específico. Decorator
É a classe abstrata do decorator, que também é Component
a implementação da interface. ConcreteDecoratorA
e ConcreteDecoratorB
são classes de implementação de decorador concreto que mantêm Component
uma referência a um objeto e executam funcionalidade adicional quando uma ação é chamada.
Na main
função, primeiro criamos o objeto de componente concreto component
. Em seguida, o decorador é criado decoratorA
e o objeto componente é passado como parâmetro. Em seguida, criamos o decorador decoratorB
e passamos o decorador decoratorA
como parâmetro. Por fim, a operação de chamar o decorador decoratorB
realmente executará a operação do decorador na ordem da cadeia do decorador e, finalmente, executará a operação do componente específico.
A saída é a seguinte:
执行装饰器B的操作
执行装饰器A的操作
执行基本操作
Como você pode ver, o padrão decorador nos permite adicionar novas funções dinamicamente através da combinação de decoradores sem modificar componentes específicos. No exemplo acima, o decorador A e o decorador B, respectivamente, adicionam operações adicionais sem afetar as funções originais de componentes específicos.
Explicação dos cenários de uso:
O modo Decoração é aplicável aos seguintes cenários:
- Quando a funcionalidade ou responsabilidade precisa ser adicionada dinamicamente sem modificar os objetos existentes.
- Quando você precisa adicionar funcionalidade de forma independente a várias propriedades de um objeto, pode usar vários decoradores para combinar.
- O padrão decorador fornece flexibilidade quando um objeto precisa adicionar, remover ou alterar a funcionalidade dinamicamente em tempo de execução.
Links de Documentação:
Aqui estão alguns links para documentação sobre o padrão Decorator para aprender mais sobre o padrão:
- Design Patterns: Elements of Reusable Object-Oriented Software por Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides (livro GOF)
- Head First Design Patterns por Eric Freeman, Elisabeth Robson, Bert Bates e Kathy Sierra
- Padrão decorador - padrões de design Java (JournalDev)
- Padrão decorador - Guru de refatoração (Guru de refatoração)
Produtos que atualmente usam o padrão decorador:
O padrão decorador é um padrão de design comum amplamente utilizado no desenvolvimento de software. Muitas bibliotecas, estruturas e aplicativos de software livre usam o padrão decorador. Aqui estão alguns exemplos de produtos que atualmente usam o padrão decorator:
- Fluxos de entrada e saída na biblioteca de classes Java IO.
- Classes decoradoras em componentes Java AWT e Swing GUI, como
JScrollPane
,JToolBar
etc. - Middleware em estruturas da web, como middleware de roteamento em Express.js, middleware de autenticação, etc.
- A função de filtro no software de processamento de imagem pode adicionar dinamicamente diferentes efeitos de filtro através do modo decorador.
- O sistema de equipamento do personagem no desenvolvimento do jogo pode adicionar dinamicamente diferentes efeitos de equipamento ao personagem por meio do modo decorador.