当前位置: 首页 > article >正文

【设计模式】【结构型模式(Structural Patterns)】之装饰模式(Decorator Pattern)

1. 设计模式原理说明

装饰模式(Decorator Pattern) 是一种结构型设计模式,它允许在不改变对象接口的前提下,动态地给对象增加额外的责任或功能。这种模式创建了一个装饰类,用于包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

主要角色
  1. Component(组件):定义了一个对象接口,可以给这些对象动态地添加职责。
  2. ConcreteComponent(具体组件):定义了一个具体的对象,也可以给这个对象添加一些责任。
  3. Decorator(装饰器):持有一个 Component 对象的实例,并定义了一个与 Component 接口一致的接口。
  4. ConcreteDecorator(具体装饰器):向组件添加新的责任,通常通过在其前后添加行为来实现。

2. UML 类图及解释

UML 类图
+-----------------+                +-----------------+
|    Component    |                | ConcreteComponent|
|-----------------|                |-----------------|
| + operation(): void|             | + operation(): void|
+-----------------+                +-----------------+
         ^                             ^
         |                             |
         |                             |
         v                             v
+-----------------+
|    Decorator    |
|-----------------|
| - component: Component  |
| + setComponent(component: Component)|
| + operation(): void            |
+-----------------+
         ^
         |
         |
         v
+-----------------+                +-----------------+
| ConcreteDecoratorA|             | ConcreteDecoratorB|
|-----------------|                |-----------------|
| + operation(): void|             | + operation(): void|
| + addedBehavior(): void|         | + addedBehavior(): void|
+-----------------+                +-----------------+
类图解释
  • Component:定义了一个对象接口,可以给这些对象动态地添加职责。
  • ConcreteComponent:定义了一个具体的对象,也可以给这个对象添加一些责任。
  • Decorator:持有一个 Component 对象的实例,并定义了一个与 Component 接口一致的接口。装饰器可以在其前后添加行为。
  • ConcreteDecoratorA 和 ConcreteDecoratorB:具体装饰器,向组件添加新的责任,通常通过在其前后添加行为来实现。

3. 代码案例及逻辑详解

Java 代码案例
// 组件接口
interface Component {
    void operation();
}

// 具体组件
class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("ConcreteComponent operation");
    }
}

// 装饰器
abstract class Decorator implements Component {
    protected Component component;

    public void setComponent(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        if (component != null) {
            component.operation();
        }
    }
}

// 具体装饰器 A
class ConcreteDecoratorA extends Decorator {
    @Override
    public void operation() {
        super.operation();
        addedBehavior();
    }

    private void addedBehavior() {
        System.out.println("ConcreteDecoratorA added behavior");
    }
}

// 具体装饰器 B
class ConcreteDecoratorB extends Decorator {
    @Override
    public void operation() {
        super.operation();
        addedBehavior();
    }

    private void addedBehavior() {
        System.out.println("ConcreteDecoratorB added behavior");
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();
        ConcreteDecoratorA decoratorA = new ConcreteDecoratorA();
        ConcreteDecoratorB decoratorB = new ConcreteDecoratorB();

        decoratorA.setComponent(component);
        decoratorB.setComponent(decoratorA);

        decoratorB.operation();
        // 输出:
        // ConcreteComponent operation
        // ConcreteDecoratorA added behavior
        // ConcreteDecoratorB added behavior
    }
}
C++ 代码案例
#include <iostream>

// 组件接口
class Component {
public:
    virtual void operation() = 0;
    virtual ~Component() {}
};

// 具体组件
class ConcreteComponent : public Component {
public:
    void operation() override {
        std::cout << "ConcreteComponent operation" << std::endl;
    }
};

// 装饰器
class Decorator : public Component {
protected:
    Component* component;

public:
    void setComponent(Component* component) {
        this->component = component;
    }

    void operation() override {
        if (component != nullptr) {
            component->operation();
        }
    }
};

// 具体装饰器 A
class ConcreteDecoratorA : public Decorator {
public:
    void operation() override {
        Decorator::operation();
        addedBehavior();
    }

    void addedBehavior() {
        std::cout << "ConcreteDecoratorA added behavior" << std::endl;
    }
};

// 具体装饰器 B
class ConcreteDecoratorB : public Decorator {
public:
    void operation() override {
        Decorator::operation();
        addedBehavior();
    }

    void addedBehavior() {
        std::cout << "ConcreteDecoratorB added behavior" << std::endl;
    }
};

// 客户端
int main() {
    Component* component = new ConcreteComponent();
    Decorator* decoratorA = new ConcreteDecoratorA();
    Decorator* decoratorB = new ConcreteDecoratorB();

    decoratorA->setComponent(component);
    decoratorB->setComponent(decoratorA);

    decoratorB->operation();
    // 输出:
    // ConcreteComponent operation
    // ConcreteDecoratorA added behavior
    // ConcreteDecoratorB added behavior

    delete component;
    delete decoratorA;
    delete decoratorB;

    return 0;
}
Python 代码案例
from abc import ABC, abstractmethod

# 组件接口
class Component(ABC):
    @abstractmethod
    def operation(self):
        pass

# 具体组件
class ConcreteComponent(Component):
    def operation(self):
        print("ConcreteComponent operation")

# 装饰器
class Decorator(Component):
    def __init__(self, component: Component):
        self._component = component

    def operation(self):
        if self._component:
            self._component.operation()

# 具体装饰器 A
class ConcreteDecoratorA(Decorator):
    def operation(self):
        super().operation()
        self.added_behavior()

    def added_behavior(self):
        print("ConcreteDecoratorA added behavior")

# 具体装饰器 B
class ConcreteDecoratorB(Decorator):
    def operation(self):
        super().operation()
        self.added_behavior()

    def added_behavior(self):
        print("ConcreteDecoratorB added behavior")

# 客户端
if __name__ == "__main__":
    component = ConcreteComponent()
    decorator_a = ConcreteDecoratorA(component)
    decorator_b = ConcreteDecoratorB(decorator_a)

    decorator_b.operation()
    # 输出:
    # ConcreteComponent operation
    # ConcreteDecoratorA added behavior
    # ConcreteDecoratorB added behavior
Go 代码案例
package main

import "fmt"

// 组件接口
type Component interface {
    Operation()
}

// 具体组件
type ConcreteComponent struct{}

func (c *ConcreteComponent) Operation() {
    fmt.Println("ConcreteComponent operation")
}

// 装饰器
type Decorator struct {
    component Component
}

func (d *Decorator) SetComponent(component Component) {
    d.component = component
}

func (d *Decorator) Operation() {
    if d.component != nil {
        d.component.Operation()
    }
}

// 具体装饰器 A
type ConcreteDecoratorA struct {
    Decorator
}

func (c *ConcreteDecoratorA) Operation() {
    c.Decorator.Operation()
    c.AddedBehavior()
}

func (c *ConcreteDecoratorA) AddedBehavior() {
    fmt.Println("ConcreteDecoratorA added behavior")
}

// 具体装饰器 B
type ConcreteDecoratorB struct {
    Decorator
}

func (c *ConcreteDecoratorB) Operation() {
    c.Decorator.Operation()
    c.AddedBehavior()
}

func (c *ConcreteDecoratorB) AddedBehavior() {
    fmt.Println("ConcreteDecoratorB added behavior")
}

// 客户端
func main() {
    component := &ConcreteComponent{}
    decoratorA := &ConcreteDecoratorA{Decorator: Decorator{component: component}}
    decoratorB := &ConcreteDecoratorB{Decorator: Decorator{component: decoratorA}}

    decoratorB.Operation()
    // 输出:
    // ConcreteComponent operation
    // ConcreteDecoratorA added behavior
    // ConcreteDecoratorB added behavior
}

4. 总结

装饰模式 是一种结构型设计模式,它允许在不改变对象接口的前提下,动态地给对象增加额外的责任或功能。这种模式通过创建装饰类来包装原有类,并在保持类方法签名完整性的前提下,提供了额外的功能。

主要优点
  1. 灵活性:可以在运行时动态地添加或删除对象的责任,而不需要修改现有的代码。
  2. 可扩展性:可以很容易地通过组合不同的装饰器来实现复杂的功能。
  3. 符合开闭原则:可以在不修改现有代码的情况下,通过添加新的装饰器来扩展功能。
主要缺点
  1. 增加了系统的复杂性:装饰模式会引入许多小类,这可能会使系统的设计变得更复杂。
  2. 调试困难:由于装饰器可以层层嵌套,调试时可能难以跟踪到最终的行为。
适用场景
  • 当需要在运行时动态地给对象添加功能时。
  • 当需要扩展类的功能,但又不想使用继承的方式时。
  • 当系统需要提供多种可选功能,且这些功能可以自由组合时。

http://www.kler.cn/a/412112.html

相关文章:

  • Spring Boot 动态数据源切换
  • 设计模式——业务代表模式
  • 计算机网络的发展
  • GitLab|应用部署
  • .net core MVC入门(一)
  • 【vue】vue中插槽slot的用法详解
  • WordPress文章目录插件,LuckyWP Table of Contents自动生成文章插件
  • vue图片导入的几种方式及优劣对比
  • 通用网络安全设备之【防火墙】
  • YOLOX的正负样本分配问题
  • 如何使用Postman优雅地进行接口自动加密与解密
  • Rust学习(十):计算机科学简述
  • 网络基础二
  • 掌握 Spring 事务管理:深入理解 @Transactional 注解(二)
  • HTTP 缓存技术
  • Cannot find a valid baseurl for repo: centos-sclo-rh/x86_64
  • Linux的前台进程和后台进程
  • Git旧文件覆盖引发思考
  • Day 27 贪心算法 part01
  • 排序算法(六)--堆排序
  • Linux17 Git 指令
  • NIO三大组件
  • OpenAI 是怎么“压力测试”大型语言模型的?
  • C#中面试的常见问题005
  • 【ArcGIS Pro实操第10期】统计某个shp文件中不同区域内的站点数
  • 探索Python自动化新境界:Helium库揭秘