设计模式-装饰模式

文章目录

  • 一、简介
  • 二、基本概念
  • 三、装饰模式的结构和实现
    • 类图解析:
    • 装饰器的实现方式
      • 继承实现:
      • 组合实现:
      • 继承和组合对比
  • 四、装饰模式的应用场景
  • 五、与其他模式的关系
  • 六、总结

一、简介

装饰模式是一种结构型设计模式,它允许动态地向对象添加额外的功能。

二、基本概念

在这里插入图片描述

  1. 装饰模式定义:在不改变原有对象结构的情况下,通过对其进行包装拓展,以达到增强功能的目的。
  2. 装饰器角色:负责给组件对象附加额外的功能,实现了与组件具有相同接口的装饰器类。
  3. 组件角色:拥有核心功能的原始对象。
  4. 抽象组件角色:定义了组件对象的接口,可以是抽象类或接口。
  5. 具体组件角色:实现了抽象组件角色的具体对象。

三、装饰模式的结构和实现

类图解析:

// 抽象组件角色
public interface Component {void operation();
}// 具体组件角色
public class ConcreteComponent implements Component {public void operation() {// 实现核心功能System.out.println("这是具体组件角色的核心功能");}
}// 装饰器角色
public abstract class Decorator implements Component {protected Component component;public Decorator(Component component) {this.component = component;}public void operation() {component.operation();}
}// 具体装饰器角色
public class ConcreteDecorator extends Decorator {public ConcreteDecorator(Component component) {super(component);}public void operation() {// 添加额外功能代码System.out.println("具体装饰器角色:"+"执行核心组件的功能前111");super.operation();// 添加额外功能代码System.out.println("具体装饰器角色:"+"执行核心组件的功能后2222");}
}
  1. 客户端代码示例:
Component component = new ConcreteComponent(); // 创建具体组件对象
component.operation(); // 调用核心功能Component decoratedComponent = new ConcreteDecorator(component); // 使用具体装饰器装饰组件
decoratedComponent.operation(); // 调用增强功能

在这里插入图片描述

装饰器的实现方式

继承实现:

具体装饰器继承装饰器抽象类,通过重写父类方法实现功能拓展
  1. 继承实现方式:
// 抽象组件角色
interface Component {void operation();
}// 具体组件角色
class ConcreteComponent implements Component {public void operation() {// 执行核心功能System.out.println("执行核心功能");}
}// 抽象装饰器角色
abstract class Decorator implements Component {protected Component component;public Decorator(Component component) {this.component = component;}public void operation() {component.operation();}
}// 具体装饰器角色
class ConcreteDecoratorA extends Decorator {public ConcreteDecoratorA(Component component) {super(component);}public void operation() {super.operation();// 添加额外的功能代码System.out.println("添加额外的功能代码A");}
}class ConcreteDecoratorB extends Decorator {public ConcreteDecoratorB(Component component) {super(component);}public void operation() {super.operation();// 添加额外的功能代码System.out.println("添加额外的功能代码B");}
}// 使用示例
public class Main {public static void main(String[] args) {// 创建具体组件对象Component component = new ConcreteComponent();// 创建具体装饰器对象,并包装组件对象Component decoratorA = new ConcreteDecoratorA(component);Component decoratorB = new ConcreteDecoratorB(decoratorA);// 调用装饰器的操作方法,实现功能的拓展decoratorB.operation();}
}

组合实现:

具体装饰器持有装饰器抽象类的实例,通过调用实例方法实现功能拓展。
2. 组合实现方式:

// 抽象组件角色
interface Component {void operation();
}// 具体组件角色
class ConcreteComponent implements Component {public void operation() {// 执行核心功能System.out.println("执行核心功能");}
}// 装饰器角色
class Decorator implements Component {protected Component component;public Decorator(Component component) {this.component = component;}public void operation() {component.operation();}
}// 具体装饰器角色
class ConcreteDecoratorA extends Decorator {public ConcreteDecoratorA(Component component) {super(component);}public void operation() {super.operation();// 添加额外的功能代码System.out.println("添加额外的功能代码A");}
}class ConcreteDecoratorB extends Decorator {public ConcreteDecoratorB(Component component) {super(component);}public void operation() {super.operation();// 添加额外的功能代码System.out.println("添加额外的功能代码B");}
}// 使用示例
public class Main {public static void main(String[] args) {// 创建具体组件对象Component component = new ConcreteComponent();// 创建具体装饰器对象,并包装组件对象Component decoratorA = new ConcreteDecoratorA(component);Component decoratorB = new ConcreteDecoratorB(decoratorA);// 调用装饰器的操作方法,实现功能的拓展decoratorB.operation();}
}

这两个示例中,都有一个抽象的组件角色(Component),一个具体的组件角色(ConcreteComponent),以及几个具体的装饰器角色(ConcreteDecorator)。具体装饰器角色在构造函数中接收一个组件对象,并在自身的 operation() 方法中调用组件对象的 operation() 方法,并添加额外的功能代码。

在使用示例中,我们创建了具体组件对象和具体装饰器对象,并将它们进行组合,最后调用装饰器的 operation() 方法来实现功能的拓展。

继承和组合对比

在装饰器模式中,继承实现和组合实现是两种常见的方式。它们在实现装饰器功能时略有不同:
继承实现:

  • 优点:
    • 简单直接:通过继承抽象装饰器类,具体装饰器可以直接重写方法并添加额外功能。
    • 可复用性高:可以轻松地创建多个具体装饰器,并进行组合拓展。
  • 缺点:
    • 类爆炸:每个具体装饰器都需要创建一个新的类,当装饰器数量增多时,类的数量也会大量增加。
    • 静态结构:类的组合和功能拓展是在编译时静态决定的,无法动态地改变组合方式。

组合实现:

  • 优点:
    • 灵活组合:具体装饰器持有抽象装饰器对象,可以在运行时动态地组合不同的装饰器对象,实现不同的功能拓展组合。
    • 类结构简单:相对于继承实现,不需要创建过多的具体装饰器类,类结构相对简单。
  • 缺点:
    • 代码复杂度较高:需要在具体装饰器中额外处理抽象装饰器对象的方法调用。可能需要在抽象装饰器中定义一些默认实现,以避免空指针异常。

根据具体需求和设计考虑,可以选择适合的实现方式。继承实现适用于静态且数量有限的装饰器组合,而组合实现适用于动态和灵活的装饰器组合。两种实现方式都能实现装饰器模式的基本功能,只是在代码结构和使用方式上略有差异。

四、装饰模式的应用场景

  1. 动态添加功能:当需要在不修改现有代码的情况下,动态地给对象添加新功能时,装饰模式可以很好地满足这一需求。
  2. 避免子类爆炸:利用装饰模式,可以避免通过创建大量子类来实现各种功能组合的问题。
  3. 透明性 vs. 安全性:装饰模式中的装饰器和组件具有相同的接口,使得对于客户端而言,无需关心具体是使用了原始组件还是装饰器对象,实现了透明性。

五、与其他模式的关系

  1. 装饰模式 vs. 适配器模式:装饰模式侧重于给对象动态添加功能,而适配器模式则是为了让不兼容的类能够协同工作。
  2. 装饰模式 vs. 组合模式:装饰模式和组合模式都采用了递归组合的思想,但装饰模式着重于给对象添加功能,而组合模式着重于构建对象的树形结构。
  3. 装饰模式 vs. 桥接模式:桥接模式将抽象部分和实现部分解耦,而装饰模式则是在不改变对象结构的基础上,拓展其功能。

六、总结

装饰模式通过包装对象实现功能的动态拓展,使得系统具有更高的灵活性和可扩展性。它应用广泛,在动态添加功能、避免子类爆炸等场景都很有价值。同时,要注意使用装饰模式时,保持透明性和安全性的平衡,确保装饰器和组件具有一致的接口。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/65087.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

msvcp120.dll丢失的解决方法?全面解决方法推荐

msvcp120.dll是Windows操作系统中的一个关键组件,如果丢失或损坏,可能会导致系统崩溃或无法正常运行。本文将介绍三种解决msvcp120.dll丢失问题的方法。 随着计算机应用的广泛普及,越来越多的人开始遇到各种电脑问题。其中,msvcp…

FPGA原理与结构——FIFO IP核的使用与测试

一、前言 本文介绍FIFO Generator v13.2 IP核的具体使用与例化,在学习一个IP核的使用之前,首先需要对于IP核的具体参数和原理有一个基本的了解,具体可以参考: FPGA原理与结构——FIFO IP核原理学习https://blog.csdn.net/apple_5…

算法通关村第十二关——字符串反转问题解析

前言 字符串反转是关于字符串算法里的重要问题,虽然不是太难,但需要考虑到一些边界问题。本篇文章就对几道字符串反转题目进行分析。 1.反转字符串 力扣344题,编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数…

亚马逊云科技生成式AI技术辅助教学领域,近实时智能应答2D数字人搭建

早在大语言模型如GPT-3.5等的兴起和被日渐广泛的采用之前,教育行业已经在AI辅助教学领域有过各种各样的尝试。在教育行业,人工智能技术的采用帮助教育行业更好地实现教学目标,提高教学质量、学习效率、学习体验、学习成果。例如,人…

应用案例 | 基于三维机器视觉的机器人麻袋拆垛应用解决方案

​Part.1 项目背景 在现代物流和制造行业中,麻袋的拆垛操作是一个重要且频繁的任务。传统的麻袋拆垛工作通常由人工完成,分拣效率较低,人力成本较高,现场麻袋堆叠、变形严重,垛型不规则、不固定,严重影响分…

(2023|PAMI,diffusion 综述)视觉扩散模型

Diffusion models in vision: A survey 公众号:EDPJ(添加 VX:CV_EDPJ 进交流群) 目录 0. 摘要 1. 简介 2. 通用框架 2.1 去噪扩散概率模型(DDPMs) 2.2 噪声条件评分网络(NCSNs&#xff0…

b站手机缓存文件转MP4

b站缓存的文件 音频、视频、弹幕是分开的 这里我只用到了音频和视频所以只介绍这一部分 b站的缓存视频文件和路径结构如下 默认缓存路径 内部存储\Android\data\tv.danmaku.bilil\download\89720189 文件夹结构 文件夹 c_738583 这是单个视频的缓存文件夹 进入c_738583文件夹…

10. selenium API (二)

目录 1. 多层框架/窗口定位 2. 下拉框处理 2.1 前端界面 2.2 代码 3. 针对 alert 弹窗进行操作 3.1 前端界面 3.2 代码 4. 文件提交 4.1 前端界面 4.2 代码 5. 显示等待 6. 操作浏览器滚动条 7. 截图 8. 浏览器关闭 9. 窗口切换 在上篇文章中,我们学…

day27 String类 正则表达式

String类的getBytes方法 String s "腻害"; byte[] bytes s.getBytes(StandardCharsets.UTF_8); String类的new String方法 String ss "ss我的"; byte[] gbks ss.getBytes("gbk"); String gbk new String(gbks, "gbk"); String类的…

交换机端口安全实验

文章目录 一、实验的背景与目的二、实验拓扑三、实验需求四、实验解法1. PC配置IP地址部分2. 在SW1上开启802.1X身份验证3. 创建一个用户身份验证的用户。用户名为wangdaye,密码为1234564.创建一个端口隔离组,实现三台PC无法互相访问 摘要: 本…

Kubernetes技术--使用kubeadm快速部署一个K8s集群

这里我们配置一个单master集群。(一个Master节点,多个Node节点) 1.硬件环境准备 一台或多台机器,操作系统 CentOS7.x-86_x64。这里我们使用安装了CentOS7的三台虚拟机 硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多 2.主机名称和IP地址规划 3. 初始化准备工作…

【C++技能树】继承概念与解析

Halo,这里是Ppeua。平时主要更新C,数据结构算法,Linux与ROS…感兴趣就关注我bua! 继承 0. 继承概念0.1 继承访问限定符 1. 基类和派生类对象赋值兼容转换2. 继承中的作用域3. 派生类中的默认成员函数4.友元5.继承中的静态成员6.菱…

创建性-构造者设计模式

前言 我们在使用Retrofit等这些第三方框架的时候,发现他们的使用都很方便,比如Retrofit retrofit new Retrofit.Builder().build(),和我们通常直接new一个对象不同,他是交给Builder类,通过build()函数来构造一个Retro…

2023-9-2 染色法判定二分图

题目链接&#xff1a;染色法判定二分图 #include <iostream> #include <cstring> #include <algorithm>using namespace std;const int N 100010l, M 200010;int n, m; int h[N], e[M], ne[M], idx;int color[N];void add(int a, int b) {e[idx] b, ne[id…

【Flutter】Flutter 使用 percent_indicator 实现基于百分比显示进度

【Flutter】Flutter 使用 percent_indicator 实现基于百分比显示进度 文章目录 一、前言二、安装和基本使用三、圆形百分比指示器四、线性百分比指示器五、完整示例六、总结 一、前言 今天我要为你介绍一个非常实用的Flutter包——percent_indicator。这个包允许我们基于百分比…

视频融合平台EasyCVR视频汇聚平台关于小区高空坠物安全实施应用方案设计

近年来&#xff0c;随着我国城市化建设的推进&#xff0c;高楼大厦越来越多&#xff0c;高空坠物导致的伤害也屡见不鲜&#xff0c;严重的影响到人们的生命安全。像在日常生活中一些不起眼的小东西如烟头、鸡蛋、果核、易拉罐&#xff0c;看似伤害不大&#xff0c;但只要降落的…

​7.3 项目3 贪吃蛇(控制台版) (A)​

C自学精简实践教程 目录(必读) 主要考察 模块划分 / 文本文件读取 UI与业务分离 / 模块划分 控制台交互 / 数据抽象 需求 用户输入字母表示方向&#xff0c;实现贪吃蛇游戏 规则&#xff1a;碰到边缘和碰到蛇自己都算游戏结束 输入文件 data.txt data.txt 内容如下&am…

深入探讨梯度下降:优化机器学习的关键步骤(二)

文章目录 &#x1f340;引言&#x1f340;eta参数的调节&#x1f340;sklearn中的梯度下降 &#x1f340;引言 承接上篇&#xff0c;这篇主要有两个重点&#xff0c;一个是eta参数的调解&#xff1b;一个是在sklearn中实现梯度下降 在梯度下降算法中&#xff0c;学习率&#xf…

设计模式—职责链模式(Chain of Responsibility)

目录 思维导图 什么是职责链模式&#xff1f; 有什么优点呢&#xff1f; 有什么缺点呢&#xff1f; 什么场景使用呢&#xff1f; 代码展示 ①、职责链模式 ②、加薪代码重构 思维导图 什么是职责链模式&#xff1f; 使多个对象都有机会处理请求&#xff0c;从而避免请…

应急三维电子沙盘数字孪生系统

一、简介应急三维电子沙盘数字孪生系统是一种基于虚拟现实技术和数字孪生技术的应急管理工具。它通过将真实世界的地理环境与虚拟世界的模拟环境相结合&#xff0c;实现了对应急场景的模拟、分析和决策支持。该系统主要由三维电子沙盘和数字孪生模型两部分组成。三维电子沙盘是…