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

设计模式——装饰器模式

装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许在运行时动态地给对象添加新的职责或功能。装饰器提供了比继承更灵活的替代方案来扩展类的行为,装饰器和被装饰的对象具有相同的接口,因此可以用来代替原对象。

原理

  • 组件接口(Component): 定义了基本行为,所有具体的组件和装饰器都要实现这个接口。
  • 具体组件(Concrete Component): 是原始对象,实现了组件接口。
  • 装饰器(Decorator): 包含一个指向组件接口的引用,并通过组合的方式持有一个具体组件实例;装饰器本身也实现了组件接口,这样就可以在不修改原有接口的前提下增加额外的功能。
  • 具体装饰器(Concrete Decorator): 是装饰器的具体实现,它在实现组件接口的方法时,既可以调用被装饰对象的方法,也可以在此基础上添加新功能。

Java代码示例

// 组件接口
public interface Coffee {double getCost();String getDescription();
}// 具体组件:基础咖啡
public class SimpleCoffee implements Coffee {@Overridepublic double getCost() {return 10.0;}@Overridepublic String getDescription() {return "Simple Coffee";}
}// 装饰器抽象类
public abstract class CoffeeDecorator implements Coffee {protected Coffee coffee;public CoffeeDecorator(Coffee coffee) {this.coffee = coffee;}@Overridepublic double getCost() {return coffee.getCost();}@Overridepublic String getDescription() {return coffee.getDescription();}
}// 具体装饰器:加糖咖啡
public class SugarCoffeeDecorator extends CoffeeDecorator {private static final double SUGAR_COST = 1.5;public SugarCoffeeDecorator(Coffee coffee) {super(coffee);}@Overridepublic double getCost() {return super.getCost() + SUGAR_COST;}@Overridepublic String getDescription() {return super.getDescription() + ", with sugar";}
}// 使用示例
public class Client {public static void main(String[] args) {Coffee simpleCoffee = new SimpleCoffee();System.out.println(simpleCoffee.getDescription() + ": $" + simpleCoffee.getCost());Coffee sugarCoffee = new SugarCoffeeDecorator(simpleCoffee);System.out.println(sugarCoffee.getDescription() + ": $" + sugarCoffee.getCost());}
}

想象一下你在一个咖啡店点了一杯简单的咖啡,然后又决定加糖。在现实生活中,这就像在原有的咖啡上附加了一个“加糖”的行为。在程序设计中,装饰器模式就是模拟这个过程:先创建一杯基础咖啡,然后用一个“加糖装饰器”去包裹它,使得最终得到的是带有附加功能(即加了糖)的新咖啡对象,但客户并不需要知道装饰过程,只需要按照统一的咖啡接口来操作即可。

应用场景

  • 在Java I/O库中,BufferedInputStream 和 BufferedOutputStream 就是对 InputStream 和 OutputStream 的装饰,增加了缓冲功能。
  • 在GUI编程中,按钮、文本框等控件可以通过装饰器模式添加边框、背景色等不同的外观效果。

适用性

  • 当系统需要在不影响其他对象的情况下,为单个对象添加职责或功能时。
  • 需要提供一种替代继承机制的方式来扩展对象的功能时,因为继承会带来大量的子类,而装饰器可以在运行时动态添加行为。

相关文章:

  • 基于java的 aws s3文件上传
  • DNS域名解析以及操作流程
  • 力扣 | 509. Fibonacci
  • Springboot开发的大学生宿舍共享厨房系统宿舍自习室宿舍洗衣房系统寝室系统技术文档论文功能部分
  • MySQL连续案例续集
  • Arduino开发实例-AS608光学指纹传感器驱动
  • ElasticSearch概述+SpringBoot 集成 ES
  • flutter使用get库管理路由,并设页面跳转动画和常见动画
  • 了解JavaScript 加密、混淆和生成签名
  • 逼格满满,推荐一个高效测试用例工具:XMind2TestCase !
  • 详解FreeRTOS:内存管理(高级篇—8)
  • 设计模式—— 单例设计模式
  • leetcode 动态规划(单词拆分)
  • 面向对象的三大特性
  • Kali安装Xrdp结合内网穿透实现无公网ip远程访问系统桌面
  • css属性的继承、初识值、计算值、当前值、应用值
  • es6--symbol
  • idea + plantuml 画流程图
  • iOS编译提示和导航提示
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • javascript面向对象之创建对象
  • LeetCode18.四数之和 JavaScript
  • magento2项目上线注意事项
  • Nacos系列:Nacos的Java SDK使用
  • nginx 配置多 域名 + 多 https
  • node和express搭建代理服务器(源码)
  • Otto开发初探——微服务依赖管理新利器
  • python 学习笔记 - Queue Pipes,进程间通讯
  • Spark学习笔记之相关记录
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • SQLServer插入数据
  • text-decoration与color属性
  • Vue.js源码(2):初探List Rendering
  • 反思总结然后整装待发
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 警报:线上事故之CountDownLatch的威力
  • 跨域
  • 那些被忽略的 JavaScript 数组方法细节
  • 如何学习JavaEE,项目又该如何做?
  • 做一名精致的JavaScripter 01:JavaScript简介
  • nb
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • #【QT 5 调试软件后,发布相关:软件生成exe文件 + 文件打包】
  • #android不同版本废弃api,新api。
  • #WEB前端(HTML属性)
  • (06)金属布线——为半导体注入生命的连接
  • (30)数组元素和与数字和的绝对差
  • (42)STM32——LCD显示屏实验笔记
  • (52)只出现一次的数字III
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (二)fiber的基本认识
  • (已解决)什么是vue导航守卫
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • (转)ObjectiveC 深浅拷贝学习