装饰器模式:实现类功能的动态扩展

news2024/11/27 17:54:42

一,简介

装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许在不修改原有类结构的情况下,给一个对象动态添加额外的职责。通常情况下,扩展一个类的功能我们首先会想到用继承方式来实现,但继承具有静态特征,耦合度高,并且随着扩展功能的增多,子类会很膨胀。而装饰器模式是使用组合取代继承,通过组合可以让类的扩展更加灵活多变。

装饰器模式主要包含以下角色:

  1. 抽象构件(Component):定义一个抽象接口以规范准备接收附加责任的对象。
  2. 具体构件(ConcreteComponent):实现抽象构件,为抽象构建添加基本的职责。
  3. 抽象装饰器(Decorator):含有抽象构件的引用,并且实现了抽象构建。
  4. 具体装饰器(ConcreteDecorator):实现抽象装饰器,并且每一个新的功能扩展都对应一个具体装饰器,具体装饰器之间可以相互嵌套组合。

优点

  • 动态扩展对象功能:装饰器模式遵循开闭原则,允许在不修改原有类的情况下,给对象动态添加新的功能。
  • 保证接口一致性:装饰器对象使用与被装饰对象相同的接口,保证接口一致性,让客户端调用更加简洁。
  • 细粒度的功能控制:装饰器模式允许以细粒度的方式控制对象的功能。可以根据需要选择添加不同的装饰器,组合出满足特定需求的功能组合,而不需要为每个功能组合创建独立的子类。
  • 支持装饰器的嵌套组合:装饰器模式支持嵌套使用多个装饰器,并按照一定顺序进行组合,以实现更复杂的功能扩展。通过嵌套组合,可以灵活地构建出满足特定需求的功能组合。

缺点

  • 增加了复杂性:引入装饰器模式会增加额外的类和对象,增加了系统的复杂性。如果过度使用装饰器模式,可能会导致装饰器的层级过深,代码难以理解和维护。
  • 可能影响性能:每个装饰器都需要包装被装饰对象,并在其上添加额外的功能。这可能会导致对象处理的性能有所降低,尤其是当装饰器的层级较多时。

适用场景

  • 需要在不修改现有对象代码的情况下,动态地扩展其功能。

  • 需要为一个对象提供不同的功能扩展,且这些功能扩展可以实现任意组合。

  • 需要在运行时动态地添加、删除或修改对象的功能。

  • 需要保持接口的一致性,使得客户端代码能够透明地处理被装饰对象和装饰器对象。

  • 当无法或不方便使用继承来扩展对象功能时,装饰器模式提供了一种更灵活的替代方案。

二,实现案例

案例分析

假如我们有两种手机,一个是华为手机,一个是小米手机,我们需要为二者扩展5G功能,同时又要为其集成AI功能。对于这样一种场景,我们可以用装饰器模式来实现。

代码实现

步骤1:创建抽象构件和具体构件

public interface Phone {
    void ican();
}
public class HuaWeiPhone implements Phone{
    @Override
    public void ican() {
        System.out.println("huawei capacities:call,sms,4G,huaweiStore");
    }
}
public class XiaoMiPhone implements Phone{
    @Override
    public void ican() {
        System.out.println("xiaomi capacities:call,sms,4G,xiaomiStore");
    }
}

步骤2:创建抽象装饰器

public abstract class PhoneDecorator implements Phone{
    protected Phone phone;

    public PhoneDecorator(Phone phone) {
        this.phone = phone;
    }
    public void ican(){
        phone.ican();
    }

}

步骤3:创建具体装饰器----5G装饰器

public class Phone5GDecorator extends PhoneDecorator {

    public Phone5GDecorator(Phone phone) {
        super(phone);
    }

    private void add5G() {
        System.out.println("extended capacity: 5G");
    }

    @Override
    public void ican() {
        phone.ican();
        add5G();
    }
}

步骤4:创建具体装饰器----Ai装饰器

public class PhoneAiDecorator extends PhoneDecorator{

    public PhoneAiDecorator(Phone phone) {
        super(phone);
    }
    private void addAi() {
        System.out.println("extended capacity: chatGPT");
    }

    @Override
    public void ican() {
        phone.ican();
        addAi();
    }
}

步骤5:客户端测试

public class Client {
    public static void main(String[] args) {

        System.out.println("华为普通手机:");
        Phone huawei=new HuaWeiPhone();
        huawei.ican();

        System.out.println("华为5G手机:");
        PhoneDecorator huawei5G=new Phone5GDecorator(new HuaWeiPhone());
        huawei5G.ican();

        System.out.println("集成Ai的华为5G手机:");
        PhoneDecorator huaWeiAi=new PhoneAiDecorator(huawei5G);
        huaWeiAi.ican();

    }
}

测试结果

image-20230530223926308

三,总结

本文详细介绍了装饰器模式的原理、优缺点、适用场景,并通过一个生动的例子来帮助大家理解装饰器模式。这是一种非常实用的设计模式,它通过组合而非继承的方式,给原有类动态地添加新功能,避免了类层次过于复杂的问题。希望本文能够帮助大家在实际开发中更好地运用装饰器模式,提高代码的可扩展性和可维护性。

好了,希望这篇文章对你的学习有所帮助,在此感谢你的阅读,我们下次再见!

1711edbd2bd444b1b647e09c2c3aff0d

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

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

相关文章

7步搞懂手写数字识别Mnist

大家好啊,我是董董灿。 图像识别有很多入门项目,其中Mnist 手写数字识别绝对是最受欢迎的。 该项目以数据集小、神经网络简单、任务简单为优势,并且集合了CNN网络中该有的东西,可谓麻雀虽小,五脏俱全。 非常适合新手…

Fourier分析入门——第12章——Fourier变换的性质

目录 第12章 Fourier变换的性质 12.1 引言 12.2 Fourier变换性质的相关定理 12.2.1 线性定理(Linearity) 12.2.2 伸缩性定理(Scaling) 12.2.3 时间/空间平移定理(Shift) 12.2.4 频移定理 12.2.5 调制定理(Modulation) 12.2.6 微分定理(Differentiation) 12.2.7 积分定…

冒泡排序详解(Bubble Sort)

本文已收录于专栏 《算法合集》 目录 一、简单释义1、算法概念2、算法目的3、算法思想4、算法性质 二、核心思想构建排序 三、图形展示宏观展示微观展示 四、算法实现实现思路代码实现客户端调用构造堆的方法元素交换的方法元素比较的方法 运行结果 五、算法描述1、问题描述2、…

数据库管理-第七十八期 记第一次数据库吐槽大会(20230530)

数据库管理 2023-05-30 第七十八期 记第一次数据库吐槽大会1 主席2 三六九等3 数据库吐槽大会总结 第七十八期 记第一次数据库吐槽大会 昨天晚上终于还是把Exadata X9M-2和之前用于展示RAC搭建及升级的那套库做好了ADG,这部分操作在整理后会在下个月发出来。因为之…

Python列表类型的使用

文章目录 Python中的列表类型一、列表的常用操作二、列表的增删改查三、列表常用的函数 Python中的列表类型 将各个元素用方括号([])括起来,用逗号(,)分隔开,这种形式的数据类型就是列表。各个元素的数据类…

HNU-电子测试平台与工具2-串口实验5次

计算机串口使用与测量 【实验属于电子测试平台与工具】 湖南大学信息科学与工程学院 计科 210X wolf (学号 202108010XXX) 0.环境搭建 在实验开始之前,安装好Ubuntu 20.04操作系统。(这个没有难度) 但要提醒的是,这个ubuntu是xubuntu,而且虚拟硬盘只有10GB的大小…

智警杯1.4---excel可视化

视频要点: 首先就是有数据透视表 点击数据透视表,分析,字段项目, 切片器筛选 切片器(我希望用什么对数据进行一个筛选) 跟下拉列表有点像,只不过切片器仅仅之对于数据透视表 依旧需要用su…

HBase集群搭建

hbase 1.解压HBase安装包 先 下载HBase压缩包,并解压安装文件,示例代码如下: tar -zxvf hbase-2.0.1-bin.tar.gz2. 修改配置文件 编辑 conf目录下的 hbase-env.sh文件,示例代码如下: cd conf vi hbase-env.sh添加…

压缩感知入门③基于ADMM的全变分正则化的压缩感知重构算法

压缩感知系列博客:压缩感知入门①从零开始压缩感知压缩感知入门②信号的稀疏表示和约束等距性压缩感知入门③基于ADMM的全变分正则化的压缩感知重构算法 文章目录 1. Problem2. 仿真结果3. MATLAB算法4. 源码地址参考文献 1. Problem 信号压缩是是目前信息处理领域非…

Frame Pacing

Frame Pacing是每个游戏都要遇到的问题,这里面有很多细节值得探讨。 为什么需要做Frame Pacing? 从我们的游戏线程渲染一帧到最终屏幕上绘制出一帧不是一个概念,这种间会经历CPU,GPU,屏幕合成器等多个角色的协同工作&a…

【xv6操作系统】安装、运行与调试

一、构建、装入过程 1.编写“启动代码主体代码”(在下载的xv6的原始代码上进行修改) 2.源代码进行编译、链接生成系统镜像(elf格式的目标文件) 3.将系统镜像保存起来(如保存到磁盘、flash或者网络服务器上&#xff…

上海斯歌K2 x 赛博威 | 战略合作深度交流暨签约仪式

2月16日,上海斯歌K2与赛博威进行了战略合作深度交流,并在赛博威广州科学城办公室举办战略合作签约仪式。 为满足客户在数智化建设过程中的多元化需求,上海斯歌K2与赛博威曾多次产生交集。凭借双方多年合作的良好基础,自2022年始&a…

【C++】右值引用和移动语义(详细解析)

文章目录 1.左值引用和右值引用左值引用右值引用 2.左值引用和右值引用的比较左值引用总结右值引用总结 3.右值引用的使用场景和意义知识点1知识点2知识点3知识点4总结 4.完美转发万能引用见识完美转发的使用完美转发的使用场景 1.左值引用和右值引用 传统的C语法中就有引用的…

【C++】引用 - 基本语法,注意事项,函数参数,函数返回值,本质

文章目录 1. 引用的基本语法2. 引用的注意事项3. 引用做函数参数4. 引用做函数返回值5. 引用的本质6. 常量引用 1. 引用的基本语法 作用是:给变量起别名 语法:数据类型 &别名 原名 2. 引用的注意事项 引用必须初始化引用在初始化后,不…

量子计算:基本概念

选了课程 《量子计算与量子信息》,没学过量子力学的博主实在是听不懂啊 (ㄒoㄒ) 简略整理了下 可能大概也许 明白一二都没有 的课程最开始两节的内容,如有错误欢迎指出 ~ ~ ~ 文章目录 矩阵论复空间中的矩阵矩阵上的运算 量子力学量子态基本假设 量子计算…

阿里云的内容识别技术可以实现哪些场景下的智能化应用?

阿里云的内容识别技术可以实现哪些场景下的智能化应用? [本文由阿里云代理商[聚搜云]撰写]   随着人工智能技术的快速发展,阿里云借助自身的技术和资源优势,开发了一种名为“内容识别”的技术。这项技术能够高效、准确地识别出图片、视频、…

有个规划文档,会让软件开发更有效

有个规划文档,会让软件开发更有效 中小企业,业务部门不太清楚软件生产过程 软件生产有一定的抽象和复杂性 要形成一个共识 趣讲大白话:要有点整体观 【趣讲信息科技181期】 **************************** 2019年整理出了一个目录框架 用在很多…

windows的cmd命令窗口介绍

1.打开cmd 1.1.方式一 左下角搜索:“运行” -> 打开 输入"cmd" -> 确定 1.2.方式二 直接使用快捷键 windows r 即可打开 然后输入cmd,点击确认 1.3.方式三 打开文件管理器,输入cmd,回车 即可在该文件路径下…

统计软件与数据分析Lesson16----pytorch基本知识及模型构建

统计软件与数据分析Lesson16----pytorch基本知识及模型构建 0.上节回顾0.1 一元线性回归数据生成数据处理初始数据可视化 0.2 梯度下降Gradient DescentStep 0: 随机初始化 Random InitializationStep 1: 计算模型预测值 Compute Models PredictionsStep 2: 计算损失 Compute t…

让进程能够“相互沟通”的高级方式一:匿名管道

代码运行及测试环境:linux centos7.6 在阅读这篇文章时,需要掌握OS对文件管理的基础知识(文件打开表、文件描述符、索引结点…) 前言 我们都知道进程是具有独立性的,意味着进程之间无法相互通信。但在一些情况下&…