【设计模式】结构型模式(一):适配器模式、装饰器模式

结构型模式(一):适配器模式、装饰器模式

  • 1.适配器模式(Adapter)
  • 2.装饰器模式(Decorator)
    • 2.1 主要特点
    • 2.2 组成部分
    • 2.3 示例代码
      • 2.3.1 Component 组件
      • 2.3.2 ConcreteComponent 具体组件
      • 2.3.3 Decorator 装饰器
      • 2.3.4 ConcreteDecorator 具体装饰器
      • 2.3.5 客户端代码
    • 2.4 总结

1.适配器模式(Adapter)

适配器模式Adapter Pattern)是一种结构型设计模式,其主要目的是通过适配器将一个接口转换为客户端所期望的另一个接口。这个模式允许你为现有类增加新功能,或者让它们之间兼容,而无需修改其源代码。适配器模式可以分为两类:

  • 类适配器模式:通过继承来适配一个类的接口。
  • 对象适配器模式:通过组合来适配一个类的接口。

适配器模式主要包含以下角色:

  • 目标接口Target):这是客户端所期望的接口,可以是一个类或一个接口。
  • 适配者Adaptee):这是需要适配的接口,即拥有不兼容接口的对象。
  • 适配器Adapter):这是关键部分,它 持有适配者对象的实例,并且可以 调用适配者的方法,同时 实现目标接口,从而使得适配者接口和目标接口兼容。

在这里插入图片描述

假设有一个类 AmericanPlug,其接口与我们的需求不兼容。我们希望使用这个类,但需要将其适配到我们所需的接口 ChinesePlug

// 目标接口
interface ChinesePlug {void connect();
}// 适配者
class AmericanPlug {public void plugIn() {System.out.println("American Plug is connected.");}
}// 适配器
class Adapter extends AmericanPlug implements ChinesePlug {@Overridepublic void connect() {super.plugIn();}
}public class AdapterPatternExample {public static void main(String[] args) {ChinesePlug plug = new Adapter();plug.connect(); // 输出 "American Plug is connected."}
}

在这个例子中,Adapter 类继承了 AmericanPlug 类并实现了 ChinesePlug 接口。通过这个适配器,客户端可以使用 ChinesePlug 接口,而实际上调用的是 AmericanPlug 类的方法。

适配器模式可以使得你复用现有的类,而不必修改它们的接口,同时增加了系统的灵活性和可扩展性。

2.装饰器模式(Decorator)

装饰器模式Decorator Pattern)是一种结构型设计模式,允许在运行时动态地为对象添加行为和职责,而不需要修改对象的结构。通过这种方式,可以 在不使用子类的情况下扩展对象的功能,提供了一种灵活的替代继承的方案。

2.1 主要特点

  • 动态扩展:可以在运行时动态地为对象添加功能,而不需要修改原有的类。
  • 透明性:装饰器类和被装饰的类具有相同的接口,客户端代码可以在不改变代码的情况下使用装饰后的对象。
  • 组合优于继承:避免了大量子类的产生,使代码更加灵活和可维护。

2.2 组成部分

  • Component组件):
    • 定义一个接口或抽象类,表示 被装饰的对象
    • 具体组件实现这个接口或抽象类。
  • ConcreteComponent具体组件):
    • 实现 Component 接口,提供基本的行为或功能。
  • Decorator装饰器):
    • 持有一个 Component 对象的引用。
    • 实现 Component 接口,可以在调用具体组件的方法前后添加新的行为。
  • ConcreteDecorator具体装饰器):
    • 继承自 Decorator,实现具体的装饰行为。

2.3 示例代码

以下是一个简单的 Java 示例,展示了如何使用装饰器模式为文本添加不同的格式。

2.3.1 Component 组件

// Component 组件
interface TextComponent {String getText();
}
  • TextComponent:定义了一个接口,声明了一个 getText 方法。这个接口表示 被装饰的对象 的基本行为。

2.3.2 ConcreteComponent 具体组件

// ConcreteComponent 具体组件
class SimpleText implements TextComponent {private String text;public SimpleText(String text) {this.text = text;}@Overridepublic String getText() {return text;}
}
  • SimpleText:实现了 TextComponent 接口,提供了一个具体的文本实现。
    • 属性text,存储具体的文本内容。
    • 构造方法SimpleText(String text),初始化文本内容。
    • 方法getText(),返回存储的文本内容。

2.3.3 Decorator 装饰器

// Decorator 装饰器
abstract class TextDecorator implements TextComponent {protected TextComponent component;public TextDecorator(TextComponent component) {this.component = component;}@Overridepublic String getText() {return component.getText();}
}
  • TextDecorator:抽象类,持有一个 TextComponent 对象的引用,实现了 TextComponent 接口。
    • 属性component,存储被装饰的组件。
    • 构造方法TextDecorator(TextComponent component),初始化 被装饰的组件
    • 方法getText(),调用被装饰组件的 getText 方法,返回其文本内容。这个方法在具体装饰器中可以被重写,以添加额外的行为

2.3.4 ConcreteDecorator 具体装饰器

// ConcreteDecorator 具体装饰器
class BoldTextDecorator extends TextDecorator {public BoldTextDecorator(TextComponent component) {super(component);}@Overridepublic String getText() {return "<b>" + super.getText() + "</b>";}
}class ItalicTextDecorator extends TextDecorator {public ItalicTextDecorator(TextComponent component) {super(component);}@Overridepublic String getText() {return "<i>" + super.getText() + "</i>";}
}
  • BoldTextDecorator具体的装饰器,继承自 TextDecorator,为文本添加粗体格式。
    • 方法getText(),在被装饰组件的文本内容前后添加 <b></b> 标签。
  • ItalicTextDecorator具体的装饰器,继承自 TextDecorator,为文本添加斜体格式。
    • 方法getText(),在被装饰组件的文本内容前后添加 <i></i> 标签。

2.3.5 客户端代码

// 客户端代码
public class DecoratorPatternExample {public static void main(String[] args) {// 创建一个简单的文本组件TextComponent simpleText = new SimpleText("Hello, World!");// 为简单文本添加粗体装饰TextComponent boldText = new BoldTextDecorator(simpleText);// 为粗体文本添加斜体装饰TextComponent italicBoldText = new ItalicTextDecorator(boldText);System.out.println(simpleText.getText()); // 输出原始文本: Hello, World!System.out.println(boldText.getText());   // 输出粗体文本: <b>Hello, World!</b>System.out.println(italicBoldText.getText()); // 输出斜体和粗体文本: <i><b>Hello, World!</b></i>}
}

2.4 总结

通过装饰器模式,可以在不修改原有类的情况下,动态地为对象添加新的功能。这种方式使得代码更加灵活和可扩展,避免了大量子类的产生。

  • 优点
    • 灵活性:可以在运行时动态地添加或删除功能。
    • 可扩展性:通过组合不同的装饰器,可以轻松地创建复杂的对象。
    • 代码复用:避免了大量子类的产生,减少了代码的复杂性。
  • 缺点
    • 复杂性:过多的装饰器可能会使代码变得复杂,难以维护。
    • 性能:每次调用方法时都需要额外的处理,可能会有性能开销。

装饰器模式在许多框架和库中都有应用,例如 Java I/O 流中的 BufferedInputStreamDataInputStream,以及 Spring 框架中的 AOP(面向切面编程)。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Go Energy 跨平台(GUI)应用编译和安装包制作

构建打包 energy cli 平台介绍描述windowNSIS安装包制作工具可通过 energy cli 安装linuxdpkg 命令系统自带macosenergy 仅生成 xxx.app系统自带 安装包制作 config/energy_[os].json是初始化应用时自动生成的应用配置文件&#xff0c;在编译和制作应用安装包时使用 Windows…

【Linux】进程信号全攻略(二)

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; 再谈信号的捕捉 &#x1f98b; 关于信号捕捉的细节部分&#xff08;sigaction函数&#xff09; 二&#xff1a;&#x1f525; 穿插话题 - 操作系统是怎么运…

鸿蒙的进击之路

1. 题记&#xff1a; 为什么要写鸿蒙&#xff0c;因为她是华为的&#xff0c;为什么是华为就要写&#xff0c;因为华为背负了国人太多太多的包袱&#xff0c;或点赞或抨击。 我是强烈支持华为的&#xff0c;但我会客观公正地去评价华为的产品&#xff0c;就比如这篇博文&#…

Swagger的介绍和使用方式+常用注解

介绍: 使用Swagger你只需要按照它的规范去定义接口及接口相关的信息&#xff0c;就可以做到生成接口文档&#xff0c;以及在线接口调试页面.简单来说就是我们只需要知道使用Swagger可以帮助我们后端生成接口文档 Swagger官网:https://swagger.io/ 因为单独使用Swagger会有些…

FFmpeg 4.3 音视频-多路H265监控录放C++开发十三:将AVFrame转换成AVPacket。视频编码,AVPacket 重要函数,结构体成员学习

前提&#xff1a; 从前面的学习我们知道 AVFrame中是最原始的 视频数据&#xff0c;这一节开始我们需要将这个最原始的视频数据 压缩成 AVPacket数据&#xff0c; 我们前面&#xff0c;将YUV数据或者 RGBA 数据装进入了 AVFrame里面&#xff0c;并且在SDL中显示。 也就是说&…

QinQ VLAN技术

QinQ VLAN技术的主要作用包括扩展VLAN数量、实现私网VLAN透传、提供二层隔离和多租户环境等。以下是对这些作用的详细介绍&#xff1a; 扩展VLAN数量 解决VLAN ID不足问题&#xff1a;QinQ技术通过在原有的802.1Q标签基础上再增加一层802.1Q标签&#xff0c;从而将VLAN数量从40…

【机器学习】24. 聚类-层次式 Hierarchical Clustering

1. 优势和缺点 优点&#xff1a; 无需提前指定集群的数量 通过对树状图进行不同层次的切割&#xff0c;可以得到所需数量的簇。树状图提供了一个有用的可视化-集群过程的可解释的描述树状图可能揭示一个有意义的分类 缺点&#xff1a; 计算复杂度较大, 限制了其在大规模数据…

分析报告、调研报告、工作方案等的提示词

什么是提示词&#xff1f; 提示词的英文是Prompt&#xff0c;是你与人工智能&#xff08;AI&#xff09;进行交流的方式。简单来说&#xff0c;提示词就是你给AI的一段文字或问题&#xff0c;AI根据这段文字或问题来生成回应或完成任务。 举个例子&#xff1a;假设你在使用一…

Sentinel通过限流对微服务进行保护

目录 雪崩问题 解决雪崩问题的方法&#xff1a; 我们使用sentinel组件实现微服务的保护 一&#xff1a;下载sentinel 二.启动sentinel 三.访问&#xff1a;localhost:8080 默认的账号和密码都是sentinel 微服务整合sentinel 一.导入sentinel依赖 二.在application.yml配…

第三十篇——微分(上):如何从宏观变化了解微观趋势?

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 微分给我们带来的思维方式的变化&#xff0c;更加符合现在这个时代对于我…

Springboot项目报错记录

SpringBoot测试报错&#xff1a;Unable to find a SpringBootConfiguration, you need to use Context 该测试类所在测试包test下的包名和类路径java下的包名不一致导致的 引发以下报错 java.lang.IllegalStateException: Unable to find a SpringBootConfiguration, you need…

VTK知识学习(3)-显示圆柱

1、添加显示控件 前台界面 <WindowsFormsHost x:Name"windowHost" Grid.Row"1"/> 构造函数中添加。 private RenderWindowControl renderWindowControl new RenderWindowControl();public MainWindow(){InitializeComponent();windowHost.Child …

《FreeRTOS的配置与临界段》

目录 1.FreeRTOS配置的重要性 2.初学者使用FreeRTOSConfig.h 文件 3.“INCLUDE_”开始的宏 4.FreeRTOS 中断配置和临界段 4.1 中断简介 4.2 中断优先级分组定义 4.3优先级设置 4.4 重要的中断屏蔽寄存器 一、PRIMASK 和 FAULTMASK 寄存器 二、BASEPRI 寄存器 4.5 F…

Vue:模板 MVVM

Vue&#xff1a;模板 & MVVM 模板插值语法指令语法 MVVMdefineProperty数据代理 模板 Vue实例绑定一个容器&#xff0c;想要向容器中填入动态的值&#xff0c;就需要使用模板语法。模板语法分为插值语法和指令语法。 插值语法 插值语法很简单&#xff0c;使用{{}}包含一…

极简实现酷炫动效:Flutter隐式动画指南第三篇自定义Flutter隐式动画

目录 前言 一、TweenAnimationBuilder 二、使用TweenAnimationBuilder实现的一些动画效果 1.调整透明度的动画 2.稍微复杂点的组合动画 3.数字跳动的动画效果 前言 上两节博客分别介绍了Flutter中的隐式动画的基础知识以及使用隐式动画实现的一些动画效果。当系统提供的隐…

熵基ZKTeco考勤机门禁如何重置密码(适用于大多数彩屏门禁机)

公司的一台门禁忘记密码了打不开&#xff0c;找了很久终于找到了密码重置的方法。 1、断电拆机(机器底部的螺丝,将机器从墙上拿下来) 2、插电重启&#xff08;或者杵下底部reset小孔&#xff09; 3、机器屏幕显示被拆除&#xff08;或右上角红色小感叹号闪烁&#xff0c;后者启…

​基于学习的地铁客流动态预测智能调度方法

1 文章信息 文章题为“A Learning Based Intelligent Train RegulationMethod With Dynamic Prediction forthe Metro Passenger Flow”&#xff0c;该文于2023年发表至“IEEE TRANSACTIONS ON INTELLIGENT TRANSPORTATION SYSTEMS”。文章的核心观点是提出了一种基于学习的智…

RNA-seq 差异分析的点点滴滴(1)

引言 本系列[1])将开展全新的转录组分析专栏&#xff0c;主要针对使用DESeq2时可能出现的问题和方法进行展开。 为何使用未经标准化的计数数据&#xff1f; DESeq2 工具包在接收输入时&#xff0c;期望得到的是未经处理的原始计数数据&#xff0c;比如从 RNA-seq 或其他高通量测…

Python初始环境搭建和Pycharm的安装

Python和PyCharm安装步骤 刚学习Python编程&#xff0c;按照书上的方法安装了Python和PyCharm&#xff0c;并做练习。但是今天PyCharm软件忽然不能使用了&#xff0c;不知道什么原因。于是&#xff0c;将这两个软件全部卸载&#xff0c;在网上查找软件安装方法&#xff0c;重新…

云上拼团GO指南——腾讯云博客部署案例,双11欢乐GO

知孤云出岫-CSDN博客 目录 腾讯云双11活动介绍 一.双十一活动入口 二.活动亮点 &#xff08;一&#xff09;双十一上云拼团Go (二&#xff09;省钱攻略 &#xff08;三&#xff09;上云&#xff0c;多类型服务器供您选择 三.会员双十一冲榜活动 (一)活动内容 &#x…