设计模式 装饰模式(Decorator Pattern)

devtools/2024/12/23 8:43:42/

装饰器模式简绍

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

装饰器模式的基本结构

装饰器模式的基本结构如下:

  • Component(组件接口):定义了所有实体类和装饰器共同遵循的接口。
  • ConcreteComponent(具体组件):实现了 Component 接口的基础组件类。
  • Decorator(装饰器):实现了 Component 接口的抽象类或接口,它包含一个对 Component 类型的引用,可以用来包装具体的组件或其他装饰器。
  • ConcreteDecorator(具体装饰器):这些类扩展了 Decorator 类,并提供了额外的行为。

装饰器优缺点

优点
  • 灵活性:
    • 动态扩展功能:装饰器模式允许在不修改原有类的基础上动态地添加职责或功能,这意味着可以在运行时根据需要添加或移除特性,提供了极大的灵活性。
  • 透明性:
    • 统一接口:装饰器类和具体组件类都遵循相同的接口,这样客户端代码就可以透明地处理所有对象,无论是基础对象还是装饰过的对象。
  • 易于扩展:
    • 避免多重继承:装饰器模式提供了一种替代继承的方式,可以在不破坏现有类层次结构的情况下扩展功能,这有助于避免由于多重继承带来的复杂性和维护上的困难。
  • 符合开放封闭原则:
    • 开放封闭原则:在不修改现有代码的情况下扩展系统的功能,符合 SOLID 原则中的开放封闭原则(OCP)。
  • 简化系统:
    • 减少子类数量:通过组合而不是继承来实现功能的扩展,减少了不必要的子类数量,使类层次更加清晰简洁。
缺点
  • 对象数量增加:
    • 大量装饰器对象:如果需要多次装饰同一个对象,可能会导致系统中存在大量的装饰器对象,增加了内存消耗和垃圾回收的压力。
  • 调试困难:
    • 装饰链复杂度:当装饰器层层叠加时,调试和理解整个装饰过程可能会变得较为复杂,尤其是当装饰器之间存在交互时。
  • 性能影响:
    • 性能开销:每次通过装饰器传递方法调用都会带来一定的性能开销,尤其是在装饰器层次较多的情况下。
  • 设计复杂性:
    • 引入额外复杂性:虽然装饰器模式简化了对象层次结构,但它也可能引入新的复杂性,特别是在需要管理多个装饰器之间的关系时。

类图

  • DecoratorComponent
    • 封装接口类
  • Meizu
    • 实现对应接口
  • Xiaomi
    • 实现对应接口
  • PhoneDecorator
    • 抽象装饰器
  • AdditionalPhoneDecorator
    • 开始 强化装饰类,添加更多方法,为原有功能添加额外方法
      在这里插入图片描述

实现代码

场景

目前手里两台手机,分别是小米跟魅族之前有两个功能可以运行跟停止软件,现在需要一个关机操作,但不想去修改那么多方法,通过装饰类去增强添加一个共有的方法,可以避免更多的改动

创建 DecoratorComponent 实现类信息,封装两个接口, 分别是执行跟停止

java">public interface DecoratorComponent {public void execute();public void stop();}

创建 meizu 实现 DecoratorComponent 实现类,并初始化两个接口, 这里用meizu

java">public class Meizu implements DecoratorComponent{@Overridepublic void execute() {System.out.println("魅族启动软件");}@Overridepublic void stop() {System.out.println("魅族停止软件运行");}
}

创建 Xiaomi 实现 DecoratorComponent 实现类,并初始化两个接口

java">public class Xiaomi implements DecoratorComponent{@Overridepublic void execute() {System.out.println("小米启动软件");}@Overridepublic void stop() {System.out.println("小米停止软件运行");}
}

添加 抽象装饰类 包含前接口的所有信息

java">public abstract class PhoneDecorator implements DecoratorComponent {protected  DecoratorComponent decoratorComponent;public PhoneDecorator(DecoratorComponent decoratorComponent){this.decoratorComponent = decoratorComponent;}@Overridepublic void execute() {decoratorComponent.execute();}@Overridepublic void stop() {decoratorComponent.stop();}
}

实现抽象装饰类,扩展原有实体类的方法以及其他相关的

java">public class AdditionalPhoneDecorator extends PhoneDecorator{public AdditionalPhoneDecorator(DecoratorComponent decoratorComponent) {super(decoratorComponent);}public void shutdown(){System.out.println("手机关机");}
}

具体实现, 增强装饰类可以添加原有信息并进行强化

java">public class Main {public static void main(String[] args) {AdditionalPhoneDecorator xiaomi = new AdditionalPhoneDecorator(new Xiaomi());AdditionalPhoneDecorator meizu = new AdditionalPhoneDecorator(new Meizu());xiaomi.execute();xiaomi.stop();xiaomi.shutdown();meizu.execute();meizu.stop();meizu.shutdown();}
}
  • 动态扩展功能:
    • 装饰器模式可以在不改变原有对象的基础上,动态地给对象添加新的功能或职责。这对于扩展对象功能非常有用,因为它是通过创建新的类而不是修改现有的类来完成的。
  • 替代继承:
    • 当系统中有很多小功能需要组合在一起时,使用继承会使得类的数量呈指数增长(如果每个功能都是单独的子类)。装饰器模式可以作为一种替代继承的方法,通过组合来达到类似的效果,而且更加灵活。
  • 封装组件及其行为:
    • 装饰器通常用来包装抽象组件,这样可以在不同的时间点增加行为,而无需修改原始组件的代码。这种模式使得可以独立于其他对象来设计细节行为。
  • 提供比继承更灵活的替代方案:
    • 继承关系是静态的,是在编译期确定的;而装饰器模式提供了一种更加灵活的方式来扩展对象的功能,可以在运行时决定。
  • 透明地增强功能:
    • 在客户端看来,装饰器对象与它所装饰的组件对象是一致的,即客户端可以透明地调用它们,而不必关心它们是否被装饰。

在实际开发中,装饰器模式可以应用于很多地方,比如在Web开发中,它可以用来动态地向HTTP响应添加额外的头部信息或者对内容进行编码/解码等。


http://www.ppmy.cn/devtools/110273.html

相关文章

如何让Google收录我的网站?

其实仅仅只是收录,只要在GSC提交网址,等个两三天,一般就能收录,但收录是否会掉,这篇内容收录了是否有展现,排名,就是另外一个课题了,如果不收录,除了说明你的网站有问题&…

mysql 生产问题处理

mysql死锁处理 处理方式1 -- 查看 InnoDB 状态 SHOW ENGINE INNODB STATUS;-- 查看死锁日志部分 -- ... 省略其他输出信息 ... ------------------------ LATEST DETECTED DEADLOCK ------------------------ ... 死锁信息 ...-- 根据日志中的线程ID kill 线程 KILL 线程ID1;…

【PPT学习笔记】使用PPT制作动画/手书/视频等作品的适配性和可能性?

【PPT学习笔记】使用PPT制作动画/手书等作品的可能性? 背景前摇:(省流可不看) 最近找到另外一份新的实习工作,有很多需要用到PPT动画的地方。 然而,我们之前制作的理工科PPT全是摒弃了形式主义的艰苦朴素…

【笔记】408刷题笔记

文章目录 三对角三叉树求最小带权路径UDP报文首部和TCP报文首部IP报文首部TCP报文首部UDP报文首部 刷新和再生的区别地址译码 为了区分队空队满,可以使用三种处理方式 1)牺牲一个单元 队头指针在队尾指针的下一位置作为队满的标志 队满条件:(…

网络初识-相关概念

本篇主要介绍关于网络的相关概念~ 相关概念 局域网: 把几个电脑连接到一起,或者几台电脑连接到同一个路由器,就能构成局域网,局域网中的电脑可以相互通信。 广域网: 将多个局域网连接起来,就构成了范围更…

【扩散模型(十)】IP-Adapter 源码详解 4 - 训练细节、具体训了哪些层?

系列文章目录 【扩散模型(一)】中介绍了 Stable Diffusion 可以被理解为重建分支(reconstruction branch)和条件分支(condition branch)【扩散模型(二)】IP-Adapter 从条件分支的视…

redission中的锁分类

redis 分布式锁的核心命令 redis分布式锁的实现主要是依靠setnx和expire两个命令完成。 注意:由于setnx和expire是两个命令,会存在如果 setnx 是成功的,但是 expire 设置失败,一旦出现了释放锁失败,或 者没有手工释放…

OPENAIGC开发者大赛企业组金奖 | 深度融合大语言模型的企业级智能文本审核系统

在第二届拯救者杯OPENAIGC开发者大赛中,涌现出一批技术突出、创意卓越的作品。为了让这些优秀项目被更多人看到,我们特意开设了优秀作品报道专栏,旨在展示其独特之处和开发者的精彩故事。 无论您是技术专家还是爱好者,希望能带给您…