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

设计模式之装饰器模式:原理、实现与应用

引言

装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许你通过将对象放入包含行为的特殊封装对象中来为原对象动态添加新的行为。装饰器模式提供了一种灵活的替代方案,避免了通过继承扩展功能的局限性。本文将深入探讨装饰器模式的原理、实现方式以及实际应用场景,帮助你更好地理解和使用这一设计模式。


1. 装饰器模式的核心概念

1.1 什么是装饰器模式?

装饰器模式是一种结构型设计模式,它允许你通过将对象放入包含行为的特殊封装对象中来为原对象动态添加新的行为。装饰器模式通过组合而不是继承来实现功能的扩展,从而提高了系统的灵活性和可扩展性。

1.2 装饰器模式的应用场景
  • 动态扩展功能:当需要动态地为对象添加功能时。

  • 避免类爆炸:当通过继承扩展功能会导致类爆炸时。

  • 灵活组合:当需要灵活地组合多个功能时。


2. 装饰器模式的实现方式

2.1 基本结构

装饰器模式通常包含以下几个角色:

  • 组件接口(Component):定义被装饰对象和装饰器的共同接口。

  • 具体组件(Concrete Component):实现组件接口,是被装饰的对象。

  • 装饰器(Decorator):实现组件接口,并持有一个组件对象的引用。

  • 具体装饰器(Concrete Decorator):扩展装饰器,添加新的行为。

2.2 代码示例
// 组件接口
public interface Component {void operation();
}// 具体组件
public class ConcreteComponent implements Component {@Overridepublic void operation() {System.out.println("ConcreteComponent operation");}
}// 装饰器
public abstract class Decorator implements Component {protected Component component;public Decorator(Component component) {this.component = component;}@Overridepublic void operation() {component.operation();}
}// 具体装饰器A
public class ConcreteDecoratorA extends Decorator {public ConcreteDecoratorA(Component component) {super(component);}@Overridepublic void operation() {super.operation();addedBehavior();}private void addedBehavior() {System.out.println("ConcreteDecoratorA added behavior");}
}// 具体装饰器B
public class ConcreteDecoratorB extends Decorator {public ConcreteDecoratorB(Component component) {super(component);}@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();Component decoratedComponentA = new ConcreteDecoratorA(component);Component decoratedComponentB = new ConcreteDecoratorB(decoratedComponentA);decoratedComponentB.operation();}
}

3. 装饰器模式的最佳实践

3.1 动态扩展功能
  • 组合优于继承:通过组合实现功能的动态扩展,避免继承的局限性。

  • 灵活组合:通过装饰器模式,可以灵活地组合多个功能。

3.2 遵循开闭原则
  • 扩展性:通过装饰器模式,可以在不修改现有代码的情况下扩展系统。

  • 灵活性:装饰器模式使得代码更加灵活,易于维护和扩展。

3.3 避免过度设计
  • 简单性:在功能扩展不复杂的情况下,避免使用装饰器模式。

  • 可读性:保持代码的简洁和可读性,避免过度设计。


4. 装饰器模式的实际应用

4.1 文本格式化

在文本格式化中,装饰器模式用于动态地为文本添加格式化功能。

// 组件接口
public interface Text {String format();
}// 具体组件
public class PlainText implements Text {private String content;public PlainText(String content) {this.content = content;}@Overridepublic String format() {return content;}
}// 装饰器
public abstract class TextDecorator implements Text {protected Text text;public TextDecorator(Text text) {this.text = text;}@Overridepublic String format() {return text.format();}
}// 具体装饰器
public class BoldTextDecorator extends TextDecorator {public BoldTextDecorator(Text text) {super(text);}@Overridepublic String format() {return "<b>" + super.format() + "</b>";}
}public class ItalicTextDecorator extends TextDecorator {public ItalicTextDecorator(Text text) {super(text);}@Overridepublic String format() {return "<i>" + super.format() + "</i>";}
}// 客户端代码
public class Client {public static void main(String[] args) {Text text = new PlainText("Hello, World!");Text boldText = new BoldTextDecorator(text);Text italicBoldText = new ItalicTextDecorator(boldText);System.out.println(italicBoldText.format());}
}
4.2 咖啡订单

在咖啡订单中,装饰器模式用于动态地为咖啡添加配料。

// 组件接口
public interface Coffee {String getDescription();double getCost();
}// 具体组件
public class SimpleCoffee implements Coffee {@Overridepublic String getDescription() {return "Simple Coffee";}@Overridepublic double getCost() {return 2.0;}
}// 装饰器
public abstract class CoffeeDecorator implements Coffee {protected Coffee coffee;public CoffeeDecorator(Coffee coffee) {this.coffee = coffee;}@Overridepublic String getDescription() {return coffee.getDescription();}@Overridepublic double getCost() {return coffee.getCost();}
}// 具体装饰器
public class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee coffee) {super(coffee);}@Overridepublic String getDescription() {return super.getDescription() + ", Milk";}@Overridepublic double getCost() {return super.getCost() + 0.5;}
}public class SugarDecorator extends CoffeeDecorator {public SugarDecorator(Coffee coffee) {super(coffee);}@Overridepublic String getDescription() {return super.getDescription() + ", Sugar";}@Overridepublic double getCost() {return super.getCost() + 0.2;}
}// 客户端代码
public class Client {public static void main(String[] args) {Coffee coffee = new SimpleCoffee();coffee = new MilkDecorator(coffee);coffee = new SugarDecorator(coffee);System.out.println(coffee.getDescription() + " $" + coffee.getCost());}
}
4.3 图形绘制

在图形绘制中,装饰器模式用于动态地为图形添加边框、阴影等效果。

// 组件接口
public interface Shape {void draw();
}// 具体组件
public class Circle implements Shape {@Overridepublic void draw() {System.out.println("Drawing Circle");}
}// 装饰器
public abstract class ShapeDecorator implements Shape {protected Shape shape;public ShapeDecorator(Shape shape) {this.shape = shape;}@Overridepublic void draw() {shape.draw();}
}// 具体装饰器
public class BorderDecorator extends ShapeDecorator {public BorderDecorator(Shape shape) {super(shape);}@Overridepublic void draw() {super.draw();drawBorder();}private void drawBorder() {System.out.println("Adding Border");}
}public class ShadowDecorator extends ShapeDecorator {public ShadowDecorator(Shape shape) {super(shape);}@Overridepublic void draw() {super.draw();drawShadow();}private void drawShadow() {System.out.println("Adding Shadow");}
}// 客户端代码
public class Client {public static void main(String[] args) {Shape circle = new Circle();Shape borderedCircle = new BorderDecorator(circle);Shape shadowedBorderedCircle = new ShadowDecorator(borderedCircle);shadowedBorderedCircle.draw();}
}

5. 装饰器模式的优缺点

5.1 优点
  • 动态扩展功能:通过装饰器模式,可以动态地为对象添加功能。

  • 避免类爆炸:通过组合实现功能的扩展,避免继承导致的类爆炸。

  • 灵活组合:通过装饰器模式,可以灵活地组合多个功能。

5.2 缺点
  • 复杂性:装饰器模式增加了系统的复杂性,特别是在功能扩展复杂的情况下。

  • 设计难度:装饰器模式的设计需要较高的抽象能力,可能增加设计难度。


结语

装饰器模式是设计模式中用于动态扩展功能的经典模式之一,适用于需要灵活地为对象添加功能的场景。通过掌握装饰器模式的原理、实现方式以及最佳实践,你可以在实际开发中更好地应用这一模式。希望本文能为你的设计模式学习之旅提供一些实用的指导!


如果你有具体的需求或想要深入探讨某个主题,请告诉我,我可以进一步调整内容!

相关文章:

设计模式之装饰器模式:原理、实现与应用

引言 装饰器模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许你通过将对象放入包含行为的特殊封装对象中来为原对象动态添加新的行为。装饰器模式提供了一种灵活的替代方案&#xff0c;避免了通过继承扩展功能的局限性。本文将深入探讨装…...

c语言笔记 结构体基础

目录 基础知识 结构体定义 基础知识 在c语言中变量是有类型的&#xff0c;比如整型&#xff0c;char型&#xff0c;浮点型等&#xff0c;这些都是单一的类型&#xff0c;那么如果说我要定义一个学生的信息&#xff0c;那么这些单一的类型是不足以表达一个学生的全部信息&#…...

Vue 登录 记住密码,设置存储时间

Vue 登录 记住密码&#xff0c;设置存储时间 一、手动存储login.vue 二、使用vue-cookies插件main.jslogin.vue 一、手动存储 login.vue 提示&#xff1a; // 设置cookie方法 setCookie(loginName, password, days) {let text encryptDes(password, des123)//使用des方法加…...

C++ 学习笔记(三)—— 入门+类和对象

1、内联函数&#xff08;inline&#xff09; 内联函数主要是解决C语言的宏的缺陷提出来的&#xff1b; 宏的缺陷&#xff1a; 1&#xff09;容易出错&#xff0c;语法坑很多&#xff1b; 2&#xff09;不能调试&#xff1b; 3&#xff09;没有类型安全的检查&#xff1b; 宏的…...

KVM安全模块生产环境配置与优化指南

KVM安全模块生产环境配置与优化指南 一、引言 在当今复杂多变的网络安全环境下&#xff0c;生产环境中KVM&#xff08;Kernel-based Virtual Machine&#xff09;的安全配置显得尤为重要。本指南旨在详细阐述KVM安全模块的配置方法&#xff0c;结合强制访问控制&#xff08;M…...

基于 SSE 和 WebSocket 的在线文本实时传输工具

简介 在线文本实时传输工具支持 SSE&#xff08;Server-Sent Events&#xff09; 和 WebSocket&#xff0c;可在不同设备间快速共享和同步文本&#xff0c;适用于跨设备协作、远程办公和即时通讯。 核心功能 实时同步&#xff1a;文本输入后&#xff0c;另一端用户可立即看到…...

数图亮相第三届全国生鲜创新峰会,赋能生鲜零售数字化转型

2025年3月15-18日&#xff0c;第三届全国生鲜创新峰会在湖北宜昌召开&#xff0c;主题为“生鲜破局&#xff0c;重塑价值”。峰会汇聚行业专家、企业领袖及精英&#xff0c;探讨生鲜零售新机遇与挑战。作为领先的“智慧零售”服务商&#xff0c;数图信息科技受邀出席&#xff0…...

go 安装swagger

1、依赖安装&#xff1a; # 安装 swag 命令行工具 go install github.com/swaggo/swag/cmd/swaglatest# 安装 gin-swagger 和 swagger 文件的依赖 go get -u github.com/swaggo/gin-swagger go get -u github.com/swaggo/files 2、测试 cmd中输入&#xff1a; swag -v 3、…...

CH347使用笔记:CH347结合STM32CubeIDE实现单片机下载与调试

目录 基于 STM32CubeIDE的 CH347 JTAG/SWD调试器使用说明1. CH347驱动安装与配置2. STM32CubeIDE调试器配置2.1 打开相关工程后&#xff0c;进行以下操作2.2 openocd.exe替换2.3 脚本添加2.4 更改调试器选择 3. 下载程序4. 使用过程中可能遇到的问题4.1 CH347未插入4.2 Openocd…...

从C语言开始的C++编程生活(1)

前言 本系列文章承接C语言的学习&#xff0c;需要有C语言的基础才能学会哦。 第1篇主要讲的是有关于C的命名空间、输入和输出。 C才起步&#xff0c;都很简单呢&#xff01; 目录 前言 命名空间namespace 基本语法 作用 使用命名空间 域作用限定符 :: 基本语法 using n…...

Python F-String 深度解析:原理、用法与最佳实践

# Python F-String 深度解析&#xff1a;原理、用法与最佳实践 ## 一、引言 Python 的 F-String&#xff08;格式化字符串字面值&#xff09;自 3.6 版本引入以来&#xff0c;凭借其简洁性和高效性&#xff0c;迅速成为字符串格式化的首选方案。本文将从原理、核心用法和编码规…...

智能家居分享

因为最近沉迷智能家居&#xff0c;所以来给大家分享一些轻松改变生活体验的小家具 1&#xff1a; 智能门锁 出门忘记带钥匙是许多人都遇到过的尴尬事&#xff0c;智能门锁的出现完美解决了这个困扰。智能门锁采用指纹识别、密码、刷卡、手机等多种开锁方式&#xff0c;大大增…...

20. Excel 自动化:Excel 对象模型

一 Excel 对象模型是什么 Excel对象模型是Excel图形用户界面的层次结构表示&#xff0c;它允许开发者通过编程来操作Excel的各种组件&#xff0c;如工作簿、工作表、单元格等。 xlwings 是一个Python库&#xff0c;它允许Python脚本与Excel进行交互。与一些其他Python库&#x…...

解决uni-app授权弹框华为审核拒绝

背景&#xff1a; 在使用定位、相机、文件、电话&#xff0c;需要用户同意授权时&#xff0c;华为和vivo需要告知用户使用权限目的。 方案&#xff1a; 在uni授权时&#xff0c;弹框告诉授权目的&#xff0c;效果如下&#xff1a; 代码&#xff1a; const perListener {//…...

施耐德PLC仿真软件Modbus tcp通讯测试

安装仿真软件&#xff1a;EcoStruxure™ Control Expert - PLC 仿真器 下载地址&#xff1a;https://www.schneider-electric.cn/zh/download/document/EIO0000001719/ 配置CPU&#xff1a; 切换至仿真模式&#xff0c;系统托盘中出现仿真器图标 新建变量test&#xff0c;地址…...

软考 中级软件设计师 考点知识点笔记总结 day05

文章目录 4、栈和队列4.1、栈的定义4.2、队列定义 5、串、数组、矩阵和广义表5.1、串5.2、 数组5.3、稀疏矩阵5.4、广义表 4、栈和队列 4.1、栈的定义 线性表是具有相同数据类型的n个数据元素的有限序列&#xff0c; n为表厂。n0时 线性表是一个空表 L &#xff08;a1,a2,a3…...

1.排序算法(学习自用)

1.冒泡排序 算法步骤 相邻的元素之间对比&#xff0c;每次早出最大值或最小值放到最后或前面&#xff0c;所以形象的称为冒泡。 特点 n个数排序则进行n轮&#xff0c;每轮比较n-i次。所以时间复杂度为O(n^2)&#xff0c;空间复杂度为O(1)&#xff0c;该排序算法稳定。 代码…...

vs2017版本与arcgis10.1的ArcObject SDK for .NET兼容配置终结解决方案

因电脑用的arcgis10.1,之前安装的vs2010正常能使用AO和AE&#xff0c;安装vs2017后无法使用了&#xff0c;在重新按照新版本arcgis engine或者arcObject费时费力&#xff0c;还需要重新查找资源。 用vs2017与arc10.1的集成主要两个问题&#xff0c;1&#xff1a;安装后vs中没有…...

基于yolo11+flask打造一个精美登录界面和检测系统

这个是使用flask实现好看登录界面和友好的检测界面实现yolov11推理和展示&#xff0c;代码仅仅有2个html文件和一个python文件&#xff0c;真正做到了用最简洁的代码实现复杂功能。 测试通过环境&#xff1a; windows x64 anaconda3python3.8 ultralytics8.3.81 flask1.1.…...

用 Vue 3.5 TypeScript 重新开发3年前甘特图的核心组件

回顾 3年前曾经用 Vue 2.0 开发了一个甘特图组件&#xff0c;如今3年过去了&#xff0c;计划使用Vue 3.5 TypeScript 把组件重新开发&#xff0c;有机会的话再开发一个React版本。 关于之前的组件以前文章 Vue 2.0 甘特图组件 下面录屏是是 用 Vue 3.5 TypeScript 开发的目前…...

深入解析 SQL 事务:确保数据一致性的关键

SQL 事务 什么是 SQL 事务&#xff1f;事务的 ACID 特性原子性&#xff08;Atomicity&#xff09;:示例&#xff1a; 一致性&#xff08;Consistency&#xff09;:示例&#xff1a; 隔离性&#xff08;Isolation&#xff09;:持久性&#xff08;Durability&#xff09;:示例&am…...

复习JVM

JVM的三个主要主题: 1.java内存区域划分: a. 堆 b. 栈 c. 元数据区 d. 程序计数器 2. 类加载 a. 加载: 打开.class文件, 读取内容 b. 验证: 验证.class文件的格式是否符合要求. c. 准备: 给类对象分配内存空间 d. 解析: 初始化字符串常量 e. 初始化: 对类对象中的各个…...

C++程序设计语言笔记——抽象机制:元编程

0 使用元编程提高类型安全。 使用元编程提升类型安全的核心在于通过代码生成、编译时检查或类型约束自动化来减少运行时错误。以下分不同编程范式详细说明实现方案&#xff1a; 一、静态类型语言的编译期约束&#xff08;以C为例&#xff09; template<typename T> cl…...

基于STM32的火灾报警设备(阿里云平台)

目录 前言&#xff1a; 一、项目介绍和演示视频 二、硬件需求准备 三、硬件框图 1. 原理图 2. PCB 四、CubeMX配置 五、代码框架 前言&#xff1a; 源代码下载链接&#xff1a; https://download.csdn.net/download/m0_74712453/90474701 需要实物的可以私信博主或者…...

用uv管理python环境/项目(各种应用场景)

一、安装uv 有python的情况 pip install uvWindows powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"linux或macOS curl -LsSf https://astral.sh/uv/install.sh | sh二、换镜像源 uv不会读取pip的镜像源配置&#xff0c;所…...

java面试题之多线程

java面试题之多线程 什么是线程&#xff1f;什么是线程安全和线程不安全&#xff1f;什么是⾃旋锁&#xff1f;什么是CAS&#xff1f;什么是乐观锁和悲观锁&#xff1f;什么是AQS&#xff1f;什么是原⼦操作&#xff1f;在Java Concurrency API中有哪些原⼦类(atomic classes)&…...

FPGA-流水灯

Quartus中使用Verilog实现 根据之前所学内容&#xff0c;打开Quartus 软件&#xff0c;新建FPGA项目文件&#xff0c;建立好空项目过后&#xff0c;选择Verilog HDL File&#xff0c;因为我们要使用Verilog代码实现仿真。 详细操作可参考往期博客&#xff1a; FPGA 实验报告&a…...

browser-use WebUI + DeepSeek 基于AI的UI自动化解决方案

browser-use WebUI 一、browser-use是什么Browser-use采用的技术栈为&#xff1a; 二、browser-use webui 主要功能使用场景 三、使用教程1.python 安装2、把项目clone下来3、安装依赖4、配置环境5、启动6、配置1.配置 Agent2.配置要用的大模型3.关于浏览器的一些设置 四、Deep…...

51单片机和STM32 入门分析

51单片机和STM32是嵌入式开发中两种主流的微控制器&#xff0c;它们在架构、性能、应用场景等方面存在显著差异。以下是两者的对比分析及选择建议&#xff1a; 1. 51单片机与STM32的定义与特点 51单片机 定义&#xff1a;基于Intel 8051内核的8位微控制器&#xff0c;结构简单…...

什么是YApi?开源接口管理平台部署教程

YApi 到底是个啥&#xff1f; 各位小伙伴们好呀&#xff01;今天要给大家介绍的是一款超级好用的接口管理神器——YApi&#xff01;它是一个高效、易用、功能强大的 API 管理平台&#xff0c;简直就是开发、产品、测试人员的福音啊&#xff01;&#xff01;&#xff01;它能帮…...