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

news2025/4/3 1:11:58

  • 引言
    • 装饰器模式
    • 具体实例
      • 共有接口类
      • 具体被装饰类
      • 抽象装饰器类
      • 具体装饰器类
    • 测试
    • 装饰器模式的实际应用
      • 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;

    @Override
    public String getFace() {
        return "ugly";
    }

    @Override
    public String getColor() {
        return "black";
    }

    @Override
    public String getDressed() {
        return "naked";
    }
}

抽象装饰器类

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

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

    @Override
    public String getDressed(){
        return people.getDressed();
    }
}

具体装饰器类

化妆装饰器:

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

    @Override
    public 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.coloradmin.cn/o/2326084.html

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

相关文章

OpenCV 图形API(或称G-API)(1)

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 引言 OpenCV 图形API(或称G-API)是一个新的OpenCV模块,旨在使常规图像处理更快且更便携。通过引入一种新的基于图的执行…

学以致用,基于OpenCV的公摊面积估算程序

由于很多户型图并没有标注各个房间或者走廊的面积,亦或比较模糊,且很多人并不具备迅速口算多个小数相加再做除法的能力,本帖通过程序粗略计算公摊比例。由于非专业人士,公摊面积涉及到很多建筑学的专业公式,因此本帖只…

d2025331

目录 一、删除有序数组中的重复项II 二、删除有序数组中的重复项 三、数字转罗马格式 一、删除有序数组中的重复项II 一下写过,挺舒服! 1、统计超出2的数量有多少,仅保留2个重复数字 2、有多少次就从后往前覆盖几次 public int removeDupl…

QT6开发指南笔记(1)QT简介,安装

(1)刚刚结束了 C 的学习,谢谢阿西老师的教导,开始 QT 的学习,运用 C ,而非 QML 。 保持知识的连贯性。 QT 公司 : (2)接着介绍 QT 的安装: 提取到的…

Redis BitMap 实现签到及连续签到统计

一、引言 用户签到功能是很多应用都离不开的一个板块,单词打开、QQ达人等等为我们所熟知,这项功能该如何实现呢,一些朋友可能想当然的觉得无非将每日的签到数据记录下来不就好了,不会去细想用谁记录,如何记录才合适。 …

GO语言杂记(文章持续更新)

1、MAIN冲突 在一个文件夹下有两个go文件同时写了main函数,将会报错,main函数只能在main包中。 实则不然,有些环境下并不会报错。 2、gofmt命令---自动对齐 命令作用:将go文件代码自动缩进。 gofmt -w escapecharprac.go

OS6.【Linux】基本指令入门(5)

目录 1.配置公网IP到XShell中 2.日志 定义和作用 3.一些指令 date %Y、%m、%d、%H、%M、%S、%X、%F %s 时间戳的特点 时间戳的转换 cal cal 年份 其他选项 ★find★ whereis grep 练习 -v选项 -n选项 -i选项 多文件查找 特定目录下查找 1.配置公网IP到XShe…

Moo0 VideoResizer,简单高效压缩视频!

Moo0 VideoResizer 是一款免费、轻量级的视频压缩工具,支持通过调整文件大小、屏幕尺寸或比特率等方式实现高效视频压缩。其核心优势在于操作简单且无需破解,可直接下载安装使用‌。软件注重用户友好性,采用非破坏性压缩技术,所有…

【开发问题记录】高德地图 Web 端开发详解:高德地图 API 最佳实践指南(安装、marker添加、逆向地理编码、实际业务案例实操)

文章目录 1、引入高德地图的准备工作2、高德地图 JS API 使用方式2.1 JS API Loader2.1.1 使用 script 标签加载loader2.1.2 NPM 安装loader 2.2 script 标签加载 JS API 脚本2.2.1 同步加载2.2.2 异步加载 3、在 vue3 项目中使用3.1 安装 js api loader3.2 在组件中使用 4、实…

快速入手-基于Django-rest-framework的自身组件权限认证(九)

1、在对应的视图函数里增加认证(局部起作用,不全局生效) 导入类: from rest_framework.authentication import ( BasicAuthentication, SessionAuthentication, ) from rest_framework.permissions import IsAuthentica…

【复活吧,我的爱机!】Ideapad300-15isk拆机升级:加内存条 + 换固态硬盘 + 换电源

写在前面:本博客仅作记录学习之用,部分图片来自网络,如需引用请注明出处,同时如有侵犯您的权益,请联系删除! 文章目录 前言升级成本升级流程电池健康度加内存条和换内存条光驱位加装机械硬盘更换电池重装系…

基于Spring AI开发本地Jenkins MCP Server服务

前言 首先介绍下MCP是什么? MCP是由开发了 Claude 模型的 Anthropic 公司2024年11月提出并开源的一项开放标准,全称:Model Context Protocol,它是一个开放协议,它使 LLM 应用与外部数据源和工具之间的无缝集成成为可能…

【nvidia】Windows 双 A6000 显卡双显示器驱动更新问题修复

问题描述:windows自动更新nvidia驱动会导致只检测得到一个A6000显卡。 解决方法 下载 A6000 驱动 572.83-quadro-rtx-desktop-notebook-win10-win11-64bit-international-dch-whql.exehttps://download.csdn.net/download/qq_18846849/90554276 不要直接安装。如…

《SRv6 网络编程:开启IP网络新时代》第2章、第3章:SRv6基本原理和基础协议

背景 根据工作要求、本人掌握的知识情况,仅针对《SRv6 网络编程:开启IP网络新时代》书籍中涉及的部分知识点进行总结梳理,并与工作小组进行分享,不涉及对原作的逐字搬运。 问题 组内同事提出的问题:本文缺扩展头描述…

如何将AI模型返回的字符串转为html元素?

场景&#xff1a; 接入deepseek模型的api到我们平台&#xff0c;返回的字符串需要做下格式化处理。 返回的数据是这样的&#xff1a; {"role": "assistant","content": "<think>\n嗯&#xff0c;用户问的是“星体是什么”。首先&am…

【PCIE711-214】基于PCIe总线架构的4路HD-SDI/3G-SDI视频图像模拟源

产品概述 PCIE711-214是一款基于PCIE总线架构的4路SDI视频模拟源。该板卡为标准的PCIE插卡&#xff0c;全高尺寸&#xff0c;适合与PCIE总线的工控机或者服务器&#xff0c;板载协议处理器&#xff0c;可以通过PCIE总线将上位机的YUV 422格式视频数据下发通过SDI接口播放出去&…

突破反爬困境:SDK开发,浏览器模块(七)

声明 本文所讨论的内容及技术均纯属学术交流与技术研究目的&#xff0c;旨在探讨和总结互联网数据流动、前后端技术架构及安全防御中的技术演进。文中提及的各类技术手段和策略均仅供技术人员在合法与合规的前提下进行研究、学习与防御测试之用。 作者不支持亦不鼓励任何未经授…

rce操作

Linux命令长度突破限制 源码 <?php $param $_REQUEST[param];if ( strlen($param) < 8 ) {echo shell_exec($param); } echo执行函数&#xff0c;$_REQUEST可以接post、get、cookie传参 源码中对参数长度做了限制&#xff0c;小于8位&#xff0c;可以利用临时函数&…

LabVIEW高效溢流阀测试系统

开发了一种基于LabVIEW软件和PLC硬件的溢流阀测试系统。通过集成神经网络优化的自适应PID控制器&#xff0c;该系统能自动进行压力稳定性、寿命以及动静态性能测试。该设计不仅提升了测试效率&#xff0c;还通过智能化控制提高了数据的精确性和操作的便捷性。 ​ 项目背景&…

DataGear 5.3.0 制作支持导出表格数据的数据可视化看板

DataGear 内置表格图表底层采用的是DataTable表格组件&#xff0c;默认并未引入导出数据的JS支持库&#xff0c;如果有导出表格数据需求&#xff0c;则可以在看板中引入导出相关JS支持库&#xff0c;制作具有导出CSV、Excel、PDF功能的表格数据看板。 在新发布的5.3.0版本中&a…