【设计模式】【结构型模式(Structural Patterns)】之装饰模式(Decorator Pattern)
1. 设计模式原理说明
装饰模式(Decorator Pattern) 是一种结构型设计模式,它允许在不改变对象接口的前提下,动态地给对象增加额外的责任或功能。这种模式创建了一个装饰类,用于包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
主要角色
- Component(组件):定义了一个对象接口,可以给这些对象动态地添加职责。
- ConcreteComponent(具体组件):定义了一个具体的对象,也可以给这个对象添加一些责任。
- Decorator(装饰器):持有一个
Component对象的实例,并定义了一个与Component接口一致的接口。 - 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 {@Overridepublic void operation() {System.out.println("ConcreteComponent operation");}
}// 装饰器
abstract class Decorator implements Component {protected Component component;public void setComponent(Component component) {this.component = component;}@Overridepublic void operation() {if (component != null) {component.operation();}}
}// 具体装饰器 A
class ConcreteDecoratorA extends Decorator {@Overridepublic void operation() {super.operation();addedBehavior();}private void addedBehavior() {System.out.println("ConcreteDecoratorA added behavior");}
}// 具体装饰器 B
class ConcreteDecoratorB extends Decorator {@Overridepublic 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 behaviordelete component;delete decoratorA;delete decoratorB;return 0;
}
Python 代码案例
from abc import ABC, abstractmethod# 组件接口
class Component(ABC):@abstractmethoddef operation(self):pass# 具体组件
class ConcreteComponent(Component):def operation(self):print("ConcreteComponent operation")# 装饰器
class Decorator(Component):def __init__(self, component: Component):self._component = componentdef 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 mainimport "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. 总结
装饰模式 是一种结构型设计模式,它允许在不改变对象接口的前提下,动态地给对象增加额外的责任或功能。这种模式通过创建装饰类来包装原有类,并在保持类方法签名完整性的前提下,提供了额外的功能。
主要优点
- 灵活性:可以在运行时动态地添加或删除对象的责任,而不需要修改现有的代码。
- 可扩展性:可以很容易地通过组合不同的装饰器来实现复杂的功能。
- 符合开闭原则:可以在不修改现有代码的情况下,通过添加新的装饰器来扩展功能。
主要缺点
- 增加了系统的复杂性:装饰模式会引入许多小类,这可能会使系统的设计变得更复杂。
- 调试困难:由于装饰器可以层层嵌套,调试时可能难以跟踪到最终的行为。
适用场景
- 当需要在运行时动态地给对象添加功能时。
- 当需要扩展类的功能,但又不想使用继承的方式时。
- 当系统需要提供多种可选功能,且这些功能可以自由组合时。
相关文章:
【设计模式】【结构型模式(Structural Patterns)】之装饰模式(Decorator Pattern)
1. 设计模式原理说明 装饰模式(Decorator Pattern) 是一种结构型设计模式,它允许在不改变对象接口的前提下,动态地给对象增加额外的责任或功能。这种模式创建了一个装饰类,用于包装原有的类,并在保持类方法…...
【AI】JetsonNano启动时报错:soctherm OC ALARM
1、问题描述 将JetsonNano烧写SD卡镜像为Ubuntu20.04后,启动时报错:soctherm OC ALARM,启动失败;然后系统一直重启 2、原因分析 “soctherm OC ALARM”是检测到系统温度超过安全阈值时发出的过热警告。 “soctherm”代表系统…...
QT:生成二维码 QRCode
目录 1.二维码历史2.QT源码3.界面展示4.工程源码链接 1.二维码历史 二维码(2-Dimensional Bar Code),是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的。它是指在一维条码…...
【LeetCode刷题之路】120:三角形最小路径和的两种解法(动态规划优化)
LeetCode刷题记录 🌐 我的博客主页:iiiiiankor🎯 如果你觉得我的内容对你有帮助,不妨点个赞👍、留个评论✍,或者收藏⭐,让我们一起进步!📝 专栏系列:LeetCode…...
神经网络中常见的激活函数Sigmoid、Tanh和ReLU
激活函数在神经网络中起着至关重要的作用,它们决定了神经元的输出是否应该被激活以及如何非线性地转换输入信号。不同的激活函数适用于不同的场景,选择合适的激活函数可以显著影响模型的性能和训练效率。以下是三种常见的激活函数:Sigmoid、T…...
适用于学校、医院等低压用电场所的智能安全配电装置
引言 电力,作为一种清洁且高效的能源,极大地促进了现代生活的便捷与舒适。然而,与此同时,因使用不当或维护缺失等问题,漏电、触电事件以及电气火灾频发,对人们的生命安全和财产安全构成了严重威胁…...
基于python爬虫的智慧人才数据分析系统
废话不多说,先看效果图 更多效果图可私信我获取 源码分享 import os import sysdef main():"""Run administrative tasks."""os.environ.setdefault(DJANGO_SETTINGS_MODULE, 智慧人才数据分析系统.settings)try:from django.core.m…...
LeetCode-315. Count of Smaller Numbers After Self
目录 题目描述 解题思路 【C】 【Java】 复杂度分析 LeetCode-315. Count of Smaller Numbers After Selfhttps://leetcode.com/problems/count-of-smaller-numbers-after-self/description/ 题目描述 Given an integer array nums, return an integer array counts whe…...
根据导数的定义计算导函数
根据导数的定义计算导函数 1. Finding derivatives using the definition (使用定义求导)1.1. **We want to differentiate f ( x ) 1 / x f(x) 1/x f(x)1/x with respect to x x x**</font>1.2. **We want to differentiate f ( x ) x f(x) \sqrt{x} f(x)x wi…...
WPF关于打开新窗口获取数据的回调方法的两种方式
一种基于消息发送模式 一种基于回调机制 基于消息发送模式 父页面定义接收的_selectedPnNumberStandarMsg保证是唯一 Messenger.Default.Register<PlateReplaceApplyModel>(this, _selectedPnNumberStandarMsgToken, platePnNumberModel > { …...
复杂网络(四)
一、规则网络 孤立节点网络全局耦合网络(又称完全网络)星型网络一维环二维晶格 编程实践: import networkx as nx import matplotlib.pyplot as pltn 10 #创建孤立节点图 G1 nx.Graph() G1.add_nodes_from(list(range(n))) plt.figure(f…...
用MATLAB符号工具建立机器人的动力学模型
目录 介绍代码功能演示拉格朗日方法回顾求解符号表达式数值求解 介绍 开发机器人过程中经常需要用牛顿-拉格朗日法建立机器人的动力学模型,表示为二阶微分方程组。本文以一个二杆系统为例,介绍如何用MATLAB符号工具得到微分方程表达式,只需要…...
SQL优化与性能——数据库设计优化
数据库设计优化是提高数据库性能、确保数据一致性和支持业务增长的关键环节。无论是大型企业应用还是小型项目,合理的数据库设计都能够显著提升系统性能、减少冗余数据、优化查询响应时间,并降低维护成本。本章将深入探讨数据库设计中的几个关键技术要点…...
FPGA存在的意义:为什么adc连续采样需要fpga来做,而不会直接用iic来实现
FPGA存在的意义:为什么adc连续采样需要fpga来做,而不会直接用iic来实现 原因ADS111x连续采样实现连续采样功能说明iic读取adc的数据速率 VS adc连续采样的速率adc连续采样的速率iic读取adc的数据速率结论分析 FPGA读取adc数据问题一:读取adc数…...
我们来学mysql -- 事务之概念(原理篇)
事务的概念 题记一个例子一致性隔离性原子性持久性 题记 在漫长的编程岁月中,存在一如既往地贯穿着工作,面试的概念这类知识点,事不关己当然高高挂起,精准踩坑时那心情也的却是日了🐶请原谅我的粗俗,遇到B…...
基于特征子空间的高维异常检测:一种高效且可解释的方法
本文将重点探讨一种替代传统单一检测器的方法:不是采用单一检测器分析数据集的所有特征,而是构建多个专注于特征子集(即子空间)的检测器系统。 在表格数据的异常检测实践中,我们的目标是识别数据中最为异常的记录,这种异常性可以…...
看不见的彼方:交换空间——小菜一碟
有个蓝色的链接,先去看看两年前的题目的write up (https://github.com/USTC-Hackergame/hackergame2022-writeups/blob/master/official/%E7%9C%8B%E4%B8%8D%E8%A7%81%E7%9A%84%E5%BD%BC%E6%96%B9/README.md) 从别人的write up中了解到&…...
YOLO模型训练后的best.pt和last.pt区别
在选择YOLO模型训练后的权重文件best.pt和last.pt时,主要取决于具体的应用场景:12 best.pt:这个文件保存的是在训练过程中表现最好的模型权重。通常用于推理和部署阶段,因为它包含了在验证集上表现最好的模型权重&#x…...
Pareidoscope - 语言结构关联工具
文章目录 关于 Pareidoscope安装使用方法输入格式语料库查询 将语料库转换为 SQLite3 数据库两种语言结构之间的关联简单词素分析关联共现和伴随词素分析相关的更大结构可视化关联结构 关于 Pareidoscope Pareidoscope 是一组 用于确定任意语言结构之间 关联的工具,…...
GPT(Generative Pre-trained Transformer) 和 Transformer的比较
GPT(Generative Pre-trained Transformer) 和 Transformer 的比较 flyfish 1. Transformer 是一种模型架构 Transformer 是一种通用的神经网络架构,由 Vaswani 等人在论文 “Attention Is All You Need”(2017)中提…...
leetcode 1504. Count Submatrices With All Ones 统计全 1 子矩形
Problem: 1504. Count Submatrices With All Ones 统计全 1 子矩形 计算矩阵的前缀和,然后遍历所有的子矩阵,看是否都是1也就是面积等于长乘以宽 都是1的矩阵,可以直接计算得到结果 Code class Solution { public:int numSubmat(vector<…...
League-Toolkit:基于LCU API的英雄联盟智能辅助工具
League-Toolkit:基于LCU API的英雄联盟智能辅助工具 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 在快节奏的MOBA游…...
专业流媒体视频下载工具技术解析与使用指南
专业流媒体视频下载工具技术解析与使用指南 价值主张:高效解决流媒体内容本地化需求 在数字内容消费日益普及的今天,用户对在线视频资源的本地保存需求持续增长。m3u8-downloader作为一款专业的流媒体下载工具,专注于解决m3u8格式视频的高效…...
LFM2.5-1.2B-Thinking-GGUFGPU算力:单卡支持4并发+32K上下文稳定推理
LFM2.5-1.2B-Thinking-GGUFGPU算力:单卡支持4并发32K上下文稳定推理 1. 平台概述 LFM2.5-1.2B-Thinking-GGUF是Liquid AI推出的轻量级文本生成模型,专为低资源环境优化设计。该模型采用GGUF格式和llama.cpp运行时,提供了简洁易用的单页Web界…...
Python邮件自动化实战:基于imaplib和email库的高效邮件处理方案
1. Python邮件自动化处理的核心价值 每天早晨打开邮箱,看到堆积如山的未读邮件时,你是否感到头皮发麻?作为曾经每天要处理200封邮件的市场分析师,我完全理解这种痛苦。直到发现Python的imaplib和email这对黄金组合,我的…...
2026年高性价比个人网盘盘点:告别“空间焦虑”,谁才是真正的效率神器?
在预算有限的情况下寻找个人网盘,大多数人的第一反应是打开计算器,算出“每 GB 只要几分钱”。但作为一个在存储行业摸爬滚打多年的老兵,我要告诉你一个反直觉的事实:对于 90% 的办公族和学生来说,网盘的“空间大小”是…...
大数据核心知识全解(零基础到Hadoop专家路线)【20260324】001篇
文章目录 大数据核心知识全解(零基础到Hadoop专家路线) 一、为什么会出现大数据?(本质原因) 1. 数据来源爆炸 2. 传统技术扛不住 3. 需求倒逼 二、CNCF 是什么?(云原生核心组织) 它和大数据的关系 三、为什么 Hadoop 会流行?(3个核心原因) 1. 它解决了当时最痛的问题…...
多智能体概述
一、多智能体概述 多智能体系统通过协调多个专职智能体或组件来完成复杂流程。并非所有复杂任务都需要多智能体——单个智能体配合合适的工具与提示词往往就够用。我们何时采用多智能体模式更有价值,以及 AgentScope 支持哪些模式? 1、为什么要用多智能体…...
本地部署Qwen3大模型+OpenClaw接入实战教程:从零实现私有化AI助手
> **标签**: AI开发,大模型,Ollama,OpenClaw,Python,本地部署 > **阅读时间**: 约15分钟 > **难度**: 中级## 一、引言本地部署大模型可确保**数据不出境、不上云**,满足金融、医疗等行业的合规要求;同时长期使用成本更低,适合高频…...
RTX4090D优化版Qwen3-32B+OpenClaw:3小时搞定AI办公自动化
RTX4090D优化版Qwen3-32BOpenClaw:3小时搞定AI办公自动化 1. 为什么选择本地部署方案 去年冬天,当我第17次被飞书机器人返回的"API配额不足"提示打断工作流时,终于下定决心寻找替代方案。作为一个小型技术团队的负责人࿰…...
