Java 装饰器模式详解:动态增强对象功能

什么是装饰器模式?

装饰器模式是一种结构型设计模式,它允许在不修改原有类的情况下,动态地为对象添加额外的职责和行为。这种模式提供了一种灵活的方式来扩展对象的功能,同时避免了通过继承导致的类爆炸问题。

装饰器模式的核心思想

装饰器模式的主要目标是:

  • 动态地为对象添加新的功能
  • 提供比继承更加灵活的扩展方式
  • 遵循开闭原则(对扩展开放,对修改关闭)

UML类图

«interface»
Component
+operation() : void
ConcreteComponent
+operation() : void
«abstract»
Decorator
#Component component
+Decorator(Component component)
+operation() : void
ConcreteDecoratorA
+operation() : void
+addedBehaviorA() : void
ConcreteDecoratorB
+operation() : void
+addedBehaviorB() : void
类图解析:
  1. Component 是一个接口,定义了 operation 方法。
  2. ConcreteComponent 是实现了 Component 接口的具体类,包含基本操作。
  3. Decorator 是一个抽象类,实现了 Component 接口,并持有一个 Component 的引用。
  4. ConcreteDecoratorAConcreteDecoratorB 是具体的装饰器类,继承自 Decorator,实现了额外功能的添加。
使用:
  1. ConcreteComponent 作为核心对象,实现基本操作。
  2. 通过 ConcreteDecoratorAConcreteDecoratorB,动态地为 ConcreteComponent 添加新功能。

代码实现示例

1. 定义基础接口

// 咖啡接口
public interface Coffee {double getCost();String getDescription();
}

2. 创建基础实现类

// 基础咖啡实现
public class SimpleCoffee implements Coffee {@Overridepublic double getCost() {return 10.0;}@Overridepublic String getDescription() {return "简单咖啡";}
}

3. 创建抽象装饰器

// 抽象装饰器
public abstract class CoffeeDecorator implements Coffee {protected Coffee decoratedCoffee;public CoffeeDecorator(Coffee coffee) {this.decoratedCoffee = coffee;}@Overridepublic double getCost() {return decoratedCoffee.getCost();}@Overridepublic String getDescription() {return decoratedCoffee.getDescription();}
}

4. 创建具体装饰器

// 牛奶装饰器
public class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee coffee) {super(coffee);}@Overridepublic double getCost() {return super.getCost() + 3.0;}@Overridepublic String getDescription() {return super.getDescription() + ", 加牛奶";}
}// 糖装饰器
public class SugarDecorator extends CoffeeDecorator {public SugarDecorator(Coffee coffee) {super(coffee);}@Overridepublic double getCost() {return super.getCost() + 2.0;}@Overridepublic String getDescription() {return super.getDescription() + ", 加糖";}
}

5. 客户端使用示例

public class DecoratorDemo {public static void main(String[] args) {// 基础咖啡Coffee simpleCoffee = new SimpleCoffee();System.out.println("基础咖啡:" + simpleCoffee.getDescription());System.out.println("价格:" + simpleCoffee.getCost());// 加牛奶的咖啡Coffee milkCoffee = new MilkDecorator(simpleCoffee);System.out.println("加牛奶的咖啡:" + milkCoffee.getDescription());System.out.println("价格:" + milkCoffee.getCost());// 加糖和牛奶的咖啡Coffee sugarMilkCoffee = new SugarDecorator(new MilkDecorator(simpleCoffee));System.out.println("加糖和牛奶的咖啡:" + sugarMilkCoffee.getDescription());System.out.println("价格:" + sugarMilkCoffee.getCost());}
}

装饰器模式的优点

  1. 灵活性:可以在运行时动态添加职责
  2. 避免继承:提供了比继承更加灵活的扩展方式
  3. 单一职责:每个装饰器只负责一个特定的功能
  4. 易于扩展:添加新的装饰器不会影响现有代码

使用场景

装饰器模式适用于以下场景:

  • 需要动态添加对象功能
  • 不希望通过继承增加子类数量
  • 需要为对象添加可选的行为

注意事项

  • 装饰器模式会增加系统的复杂性
  • 多层装饰可能会导致代码难以理解
  • 尽量保持装饰器的轻量级和单一职责

结论

装饰器模式为我们提供了一种灵活、优雅的方式来扩展对象功能。通过使用装饰器,我们可以在不修改原有类的情况下,动态地为对象添加新的行为和职责。

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

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

相关文章

matlab读取NetCDF文件

matlab对NetCDF文件进行信息获取和读取数据 文章目录 前言一、什么是NetCDF文件二、读取NetCDF文件数据 1.引入库 2.读入数据总结 前言 在气象学中,许多气象数据存储在NetCDF文件中,后缀为.nc,通常可以用NCL、python和MATLAB等对该…

MySQL用户管理、权限管理练习

1.使用root用户登录MySQL客户端,创建一个名为userl的用户,初始密码为123456; 创建一个名为user2的用户,无初始密码。然后,分别使用uesr1、user2登录MySQL 客户端。 2.使用root用户登录,将user2用户的密码修改为abcabc。…

SpringAOP手动模拟实现反射注解Jdk动态代理

代理 package com.xtq.aop.proxy;import com.xtq.annotations.After; import com.xtq.annotations.Before; import com.xtq.annotations.Pointcut;import java.lang.annotation.Annotation; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Invocation…

算法-字符串-3.无重复字符的最长子串

一、思路&#xff1a; 无重复针对唯一的元素首选哈希表方法 在字符串中找出最长字串——动态数组 二、使用的一些常见方法 1.HashMap a.声明 HashMap<Character,Integer> mapnew HashMap(); b.添加元素 map.put(s.charAt(i),i); c.查询是否有对应的元素存在并获取 m…

Ubuntu中安装配置交叉编译工具并进行测试

01-下载获取交叉编译工具的源码 按照博文 https://blog.csdn.net/wenhao_ir/article/details/144325141的方法&#xff0c;把imx6ull的BSP下载好后&#xff0c;其中就有交叉编译工具。 当然&#xff0c;为了将来使用方便&#xff0c;我已经把它压缩并传到了百度网盘&#xff…

Idea实现定时任务

定时任务 什么是定时任务&#xff1f; 可以自动在项目中根据设定的时长定期执行对应的操作 实现方式 Spring 3.0 版本之后自带定时任务&#xff0c;提供了EnableScheduling注解和Scheduled注解来实现定时任务功能。 使用SpringBoot创建定时任务非常简单&#xff0c;目前主要…

Cesium 问题: 添加billboard后移动或缩放地球,标记点位置会左右偏移

文章目录 问题分析原先的:添加属性——解决漂移移动问题产生新的问题:所选的经纬度坐标和应放置的位置有偏差解决坐标位置偏差的问题完整代码问题 添加 billboard 后, 分析 原先的: // 图标加载 function addStation ({lon, lat, el, testName

PHP中GD库的使用

由于我要用到php的验证码 <?php session_start();// 生成验证码 $random_code substr(md5(uniqid(mt_rand(), true)), 0, 6);// 将验证码保存到 session 中 $_SESSION[captcha] $random_code;// 创建图片 $font 6; $image_width 100; $image_height 40;// 创建图像 $…

精确的单向延迟测量:使用普通硬件和软件

论文标题&#xff1a;Precise One-way Delay Measurement with Common Hardware and Software&#xff08;精确的单向延迟测量&#xff1a;使用普通硬件和软件&#xff09; 作者信息&#xff1a;Maciej Muehleisen 和 Mazen Abdel Latif&#xff0c;来自Ericsson Research Eri…

数据挖掘:一、Weka软件的基本操作

实验目的和要求 了解Weka软件的使用 实验环境 Windows11 Weka3.8.6 实验内容与过程 实验内容 1、了解Weka使用的一般步骤 2、利用Weka,对数据集进行关联规则挖掘及数据分类 3、记录操作步骤、使用的数据、最终的结果 实验过程 首先打开weka下载官网,选择合适

【Notepad++】---设置背景为护眼色(豆沙绿)最新最详细

在编程的艺术世界里&#xff0c;代码和灵感需要寻找到最佳的交融点&#xff0c;才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里&#xff0c;我们将共同追寻这种完美结合&#xff0c;为未来的世界留下属于我们的独特印记。 【Notepad】---设置背景为护眼色&#xf…

【微服务】SpringBoot 对接飞书多维表格事件回调监听流程详解

目录 一、前言 二、前置准备 2.1 创建一个应用 2.2 准备一张测试使用的多维表 2.3 获取对接文档 2.4 工程中添加SDK 三、对接过程 3.1 配置Encrypt Key 和 Verification Token 3.2 配置订阅方式 3.3 添加事件 3.4 申请权限 3.5 编写订阅代码 3.6 订阅文档事件 3.…

从0开始边做边学,用vue和python做一个博客,非规范化项目,怎么简单怎么弄,跑的起来有啥毛病解决啥毛病(三)

基础的内容都差不多了&#xff0c;开始研究文章详情页的内容设计&#xff0c;程序员嘛肯定要用markdown编辑了&#xff0c;找了一些发现这个md-editor看着还不错&#xff0c;文档介绍页比较清晰&#xff0c;用着也比较简单。 md-editor安装配置使用Mock.js模拟请求接口mock.js …

pdf转word/markdown等格式——MinerU的部署:2024最新的智能数据提取工具

一、简介 MinerU是开源、高质量的数据提取工具&#xff0c;支持多源数据、深度挖掘、自定义规则、快速提取等。含数据采集、处理、存储模块及用户界面&#xff0c;适用于学术、商业、金融、法律等多领域&#xff0c;提高数据获取效率。一站式、开源、高质量的数据提取工具&…

SWIRL:有望成为2025年顶级AI搜索引擎

现在几乎每家公司都会有内部文档系统&#xff0c;如阿里的语雀、钉钉&#xff0c;字节的飞书&#xff0c;Confluence&#xff0c;印象笔记等等都可以提供给B端在局域网部署。因此&#xff0c;如果能把搜索功能做得高效&#xff0c;就能提高自家产品的竞争力。 想象一下&#xf…

Android环境搭建

Android环境搭建 第一步&#xff1a;安装 Homebrew 执行以下命令来安装 Homebrew&#xff1a; /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"检测是否安装成功&#xff1a; brew --version第二步&#xff1a;安装 No…

【Homework】【8】Learning resources for DQ Robotics in MATLAB

作业任务 创建一个名为“VS050RobotDH”的类&#xff0c;该类代表Denso VS050机器人&#xff0c;其DH参数如下表所示&#xff0c;并且完全由旋转关节组成。&#xff08;请记住第6课的内容&#xff09; θ \theta θ d d d a a a α \alpha α − π -\pi −π0.3450 π 2 \fra…

jenkins邮件的配置详解

Jenkins邮件的配置涉及多个步骤和细节,以下是详细的配置指南: 一、前期准备 确定邮件服务:明确Jenkins将要使用的邮件服务,如QQ邮箱、163邮箱、公司邮箱(基于Microsoft 365或Exchange Server)等。获取SMTP配置信息:根据邮件服务类型,获取相应的SMTP服务器地址、端口号…

算法-字符串-43.字符串相乘

一、题目 二、思路解析 1.思路&#xff1a; 1.双重for循环&#xff0c;倒序依次相乘 2.在倒序处理进位问题 3.最后返回参数的类型是string&#xff0c;用StringBuilder拼接&#xff0c;再转换为字符串 2.常用方法&#xff1a; 1.equals,比较对象内容是否一致 "0".eq…

Clip使用

简单使用 img {width: 300px;height: 300px;clip-path: polygon(50% 0%, 0% 100%, 100% 100%) } 图片如下&#xff1a; img {width: 300px;height: 300px;clip-path: polygon(0% 0%, 100% 100%, 50% 100%) } 图片如下&#xff1a; 我们给出对应的点&#xff0c;浏览器就能进…