装饰器模式:如何用Java打扮一个对象?

  • 引言
    • 装饰器模式
    • 具体实例
      • 共有接口类
      • 具体被装饰类
      • 抽象装饰器类
      • 具体装饰器类
    • 测试
    • 装饰器模式的实际应用
      • Java I/O 体系
      • 游戏开发中的角色装备系统
  • 总结

引言

在生活中,我们都知道一句话,“人靠衣装马靠鞍”,如果想要让自己在别人眼里看起来更加好看,更加丰富多彩,就得要学会打扮自己,为自己化妆,为自己穿好看的衣服,学会了打扮的本领,那么我们就可以轻松应对不同场合的需求。无论是日常通勤的简约风,还是晚宴的华丽造型,我们只需在“基础自我”上叠加不同的装饰元素,而无需改变本质——这种灵活性和可扩展性,恰恰是装饰器模式(Decorator Pattern) 在软件设计中的精髓。
想象一下,我们在实际生活中,是不是如果当前的脸上瑕疵较多,就使用素颜霜遮盖一下,当前的皮肤太黑,也可以通过化妆技术变白。穿衣更是如此,我们可以选择穿简约风格的衣服,在得知今晚要参加晚宴后,还可以换上一套隆重的礼服。这些操作都不需要我们变成一个新的人(继承的方法),只需要我们使用一下化妆或者是换装的方法就可以(装饰器的方法)。
本文通过对一个男孩打扮和换装的例子,来深入了解装饰器模式。

装饰器模式

装饰器模式是一个结构性设计模式,允许在不修改原有类的情况下,为对象动态添加新功能,而不会影响其他对象。通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。针对目标方法进行增强,提供新的功能或者额外的功能。也就是例子中的我们把需要打扮的男孩放到化妆台前或者是衣柜前,然后这个男孩回来的时候就是一个打扮过的了,比原来更加丰富多彩。
首先看一下装饰器模式的四大核心组件:
在这里插入图片描述
Component: 所有可以被装饰的类要继承的接口,同时,装饰器类也要继承该接口,这样可以保证装饰前的对象和经过装饰后返回的对象是同一个类型。
ConcreteComponent: 具体要装饰的类,实现Component接口,实现被装饰前的方法。
AbstractDecorator: 抽象装饰器类,同样实现AbstractDecorator接口,为什么要有这个抽象类呢?其实就是可以在这个抽象类中提前把被装饰的对象原始的功能实现,这样具体的装饰器类就不用每个都重复实现原本被装饰前的对象的功能了,只需要关注如何装饰它。
ConcreteDecorator: 具体的装饰器类,继承抽象装饰器类,它需要装饰的那个对象的原来的方法已经在抽象装饰器中实现了,所以这个类只需要关注需要对被装饰的类做出哪些装饰就行了。

具体实例

本文设计的例子是对一个男孩进行打扮,通过化妆台(化妆装饰器 MakeupDecorator)和衣帽间(DressupSimpleDecoratorDressupGrandDecorator )对男孩进行两次装饰,最终男孩原本的模样(方法)变成装饰后的模样。

共有接口类

所有可以被装饰的类都要继承这个接口。

//可以进行装饰需要满足的接口
interface PersonComponent{public String getFace();public String getColor();public String getDressed();
}

具体被装饰类

男孩需要被打扮,所以它实现上面的WaitForDecorator接口。

//等待被装饰的类
class Boy implements PersonComponent{String face;String color;String dress;@Overridepublic String getFace() {return "ugly";}@Overridepublic String getColor() {return "black";}@Overridepublic String getDressed() {return "naked";}
}

抽象装饰器类

所有的具体装饰器类都要继承该接口,可以避免重复的代码多次编写,将需要被装饰的对象在这个抽象装饰器类中将原本的功能实现一遍,这样具体装饰器类就只需要关注具体需要装饰的功能了。

//装饰器基类
abstract class PersonDecorator implements PersonComponent{private People people;public PeopleDecorator(People people){this.people=people;}@Overridepublic String getFace(){return people.getFace();}@Overridepublic String getColor(){return people.getColor();}@Overridepublic String getDressed(){return people.getDressed();}
}

具体装饰器类

化妆装饰器:

class MakeupDecorator extends PersonDecorator{public MakeupDecorator(People people) {super(people);}@Overridepublic String getFace(){return "make ugly to pretty";}@Overridepublic String getColor(){return "make black to white";}
}

简约风衣着装饰器:

class DressupSimpleDecorator extends PersonDecorator{public DressupSimpleDecorator(People people) {super(people);}public String getDressed(){return "wearing simple cloth";}
}

宴会衣着装饰器:


class DressupGrandDecorator extends PersonDecorator{public DressupGrandDecorator(People people) {super(people);}public String getDressed(){return "wearing grand cloth";}}

测试

public static void main(String[] args) {PersonComponent boy =new Boy();//男孩先穿了简约衣服打算出门吃海底捞boy = new DressupSimpleDecorator(boy);//男孩简单地化了个妆boy = new MakeupDecorator(boy);//男孩突然被通知需要参加一场宴会,就换上了华丽的衣服。boy = new DressupGrandDecorator(boy);System.out.println(boy.getColor());System.out.println(boy.getFace());System.out.println(boy.getDressed());}

运行结果如下:

make black to white
make ugly to pretty
wearing grand cloth

可以看见男孩化了妆并且变得漂亮了,最后穿上的是后来穿的华丽衣服。

装饰器模式的实际应用

下面列举了几个典型的应用场景:

Java I/O 体系

Java 的 I/O 类库大量使用了装饰器模式,例如 BufferedReader、InputStreamReader、FileInputStream 等,允许开发者通过不同的装饰器动态增强流的功能。

BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("data.txt")));

这里,BufferedReader 作为装饰器,增强了 InputStreamReader,提供了缓存功能以提高读取效率。其中他们的共同接口是Reader。

游戏开发中的角色装备系统

在游戏开发中,角色装备(如盔甲、武器)通常使用装饰器模式。例如,一个基础角色可以通过不同装备来增强属性,如增加攻击力、防御力等。

Character warrior = new Warrior();
warrior = new ArmorDecorator(warrior);  // 增加防御
warrior = new SwordDecorator(warrior);  // 增加攻击力

总结

装饰器模式通过“动态增强”而非“本质改变”的设计理念,为软件设计提供了高度的灵活性和可扩展性。本文以生活中“换装打扮”的生动场景为引,巧妙类比了装饰器模式的核心思想——在不修改对象自身的基础上,通过层层叠加装饰器来扩展功能。

核心价值体现:
灵活组合,动态扩展
如同男孩可根据场合自由切换妆容和服饰,装饰器模式允许在运行时动态添加或替换功能。例如,先穿简约服装,再化妆,最后换宴会礼服,每一步装饰都独立且可逆,避免继承带来的僵化性。

职责分离,结构清晰
通过抽象装饰器(PeopleDecorator)封装原始对象,将核心功能(getColor())与装饰逻辑(美白、换装)解耦。具体装饰器仅关注自身新增功能(MakeupDecorator专注美化肤色),代码可读性和维护性显著提升。

遵循开闭原则
新增装饰器(添加“配饰装饰器”)无需修改现有代码,只需继承抽象装饰器即可。这种设计支持系统的渐进式扩展,降低耦合度,符合“对扩展开放,对修改关闭”的原则。

实践启示:
装饰器模式尤其适用于需动态、透明地扩展对象功能的场景。例如,Java I/O流中BufferedReader对FileReader的增强,或Web请求处理中的中间件链式调用。本文的男孩换装案例直观展现了装饰器的链式调用特性——每次装饰均基于前一步的结果,最终形成功能叠加或覆盖的效果(最后一次换装决定最终衣着)。

总之,装饰器模式如同为对象穿上“功能外衣”,让代码在保持简洁的同时,具备应对复杂需求的优雅扩展能力,是提升系统设计弹性的重要工具。

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

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

相关文章

【Easylive】HikariCP 介绍

【Easylive】项目常见问题解答(自用&持续更新中…) 汇总版 HikariCP 是目前 Java 生态中最快、最轻量级的高性能 JDBC 连接池,被 Spring Boot 2.x 及更高版本选为 默认数据库连接池。它的名字来源于日语“光”(Hikari&#xf…

清晰易懂的Cursor实现AI编程从安装到实战TodoList开发

一、Cursor简介与安装部署 什么是Cursor? Cursor是一款基于AI的智能代码编辑器,它集成了强大的AI编程助手功能,能够通过自然语言交互帮助开发者生成、优化和调试代码。与传统的代码编辑器不同,Cursor可以理解你的编程意图&#…

【Django】教程-2-前端-目录结构介绍

【Django】教程-1-安装创建项目目录结构介绍 3. 前端文件配置 3.1 目录介绍 在app下创建static文件夹, 是根据setting中的配置来的 STATIC_URL ‘static/’ templates目录,编写HTML模板(含有模板语法,继承,{% static ‘xx’ …

注意!ChatGPT 全新 AI 图像功能延迟对免费用户开放

2025 年 3 月 25 日,OpenAI 正式宣布在 ChatGPT 中推出基于 GPT-4o 模型的全新原生图像生成功能。 这一功能允许用户通过对话生成和编辑图像,支持从写实风格到插图风格的多种形式。OpenAI 首席执行官萨姆・奥特曼(Sam Altman)在社…

优化webpack打包体积思路

Webpack 打包过大的问题通常会导致页面加载变慢,影响用户体验。可以从代码优化、依赖优化、构建优化等多个角度入手来减少打包体积: 代码优化 (1)按需加载(代码拆分) ① 路由懒加载 如果你的项目使用 Vu…

HarmonyOS Next~鸿蒙元服务开发指南:核心功能与实践

HarmonyOS Next~鸿蒙元服务开发指南:核心功能与实践 一、元服务核心概念 原子化服务定义 元服务(原子服务)是鸿蒙系统的核心架构单元,具备独立业务能力的轻量化服务模块,支持免安装、跨设备调用和智能分发…

git错误:fatal: detected dubious ownership in repository at xxxxxx

1、报错说明 这个错误通常是由于Git仓库目录的拥有者或权限问题引起的。Git检测到仓库目录的所有权可能存在不一致或不安全的情况。 通常导致此报错的可能原因: (1)文件或目录的拥有者不一致: 仓库目录中的某些文件或子目录可能…

【计算机网络】OSI七层模型完全指南:从比特流到应用交互的逐层拆解

OSI模型 导读一、概念二、模型层次结构2.1 物理层(Physical Layer)2.2 数据链路层(Data Link Layer)​2.3 ​网络层(Network Layer)​2.4 ​传输层(Transport Layer)​2.5 ​会话层&…

零基础被迫参加CTF比赛?CTF高频解题技巧与经验分享

CTF(Capture The Flag)比赛中的高频解题技巧通常涵盖了以下几类技术,涉及从逆向工程、二进制漏洞利用到Web安全、密码学等多个领域。以下是一些高频解题技巧: 1. 逆向工程(Reverse Engineering) 静态分析&a…

markdown 文件转 word

将 Markdown 文件转换为 Word 文档,可以使用多种方法。以下是几种常见的方法: 方法1:使用在线转换工具 有许多在线服务可以将 Markdown 文件转换为 Word 文档。例如: Pandoc - 一个非常流行的命令行工具,也可以用来转…

【第十三届“泰迪杯”数据挖掘挑战赛】【2025泰迪杯】【思路篇】A题解题全流程(持续更新)

【第十三届“泰迪杯”数据挖掘挑战赛】【2025泰迪杯】A题解题全流程-思路(持续更新) 写在前面: 1、A题、C题将会持续更新,陆续更新发布文章 2、赛题交流咨询Q群:1037590285 3、全家桶依旧包含: 代码、…

T11 TensorFlow入门实战——优化器对比实验

🍨 本文為🔗365天深度學習訓練營 中的學習紀錄博客🍖 原作者:K同学啊 | 接輔導、項目定制 一、前期准备 1. 导入数据 # Import the required libraries import pathlib import matplotlib.pyplot as plt import tensorflow as t…

Docker部署sprintboot后端项目

创建Docker网络 docker network create icjs 部署Redis docker run -d \--network icjs \--name redis \-p 6379:6379 \redis:latest数据持久化 docker run --restartalways --network icjs -p 6379:6379 --name redis -v /opt/docker/redis/redis.conf:/etc/redis/redis.c…

01小游戏

问题描述 小明得到了一个长度为 nn 的字符串 ss ,该字符串都是由数字 00 和 11 组成,并且下标从 11 开始,小明现在需要对这个字符串进行 qq 次操作,每次操作包含以下两种操作之一: 操作 11 :小明查询该字符…

Androidstudio开发,实现商品分类

文章目录 1. 功能需求2. 代码实现过程1. 编写布局文件2. 创建商品分类(Adapter)适配器3. 实现商品分类Activity4. 在res/values/ 下新建 array.xml ,用于添加商品分类数据5. 效果演示 6. 关于作者其它项目视频教程介绍 1. 功能需求 显示商品分…

Linux快速安装docker和docker-componse步骤

在 CentOS 7 上安装 Docker 和 Docker Compose 的步骤如下: 1. 安装 Docker 1.1. 更新系统 首先,确保你的系统是最新版本: sudo yum update -y1.2. 安装必要的包 安装 yum-utils,这是管理 YUM 源的工具: sudo yu…

VBA代码解决方案第二十三讲 EXCEL中,如何删除工作表中的空白行

《VBA代码解决方案》(版权10028096)这套教程是我最早推出的教程,目前已经是第三版修订了。这套教程定位于入门后的提高,在学习这套教程过程中,侧重点是要理解及掌握我的“积木编程”思想。要灵活运用教程中的实例像搭积木一样把自己喜欢的代码…

Pytorch--tensor.view()

在 PyTorch 中,tensor.view() 是一个常用的方法,用于改变张量(Tensor)的形状(shape),但不会改变其数据本身。它类似于 NumPy 的 reshape(),但有一些关键区别。 1. 基本用法 import …

【机器学习】——机器学习思考总结

摘要 这篇文章深入探讨了机器学习中的数据相关问题,重点分析了神经网络(DNN)的学习机制,包括层级特征提取、非线性激活函数、反向传播和梯度下降等关键机制。同时,文章还讨论了数据集大小的标准、机器学习训练数据量的…

CoAP Shell 笔记

CoAP Shell 笔记 1. 概述 CoAP (Constrained Application Protocol) 是一种专为物联网 (IoT) 中资源受限的节点和网络设计的 RESTful Web 传输协议。CoAP Shell 是一个基于命令行的交互式工具,用于与支持 CoAP 的服务器进行交互。 2. 主要功能 协议支持&#xff…