news 2025/12/29 8:00:58

Java设计模式详解--装饰器设计模式(含uml图)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java设计模式详解--装饰器设计模式(含uml图)

一,初步理解

直接举个例子:

在这个例子中,结合以上图片与uml图进行分析不难得出:

Decorator装饰器

包含滚动条与边框,是它们的父类

滚动条与边框都为ConcreteDecorator(具体装饰器)

Component

负责将装饰器与基础组件统计起来,说明每个组件与装饰器该完成什么统一的工作

比如这里,它们都需要画出来(draw())

所以显然,这里的文本框并不属于装饰器,而是属于(基础组件)

二,看题目

Componet是界面组件中的抽象父类,其TextBox子类是文本框组件,Table子类是表格组件。

Decorator是抽象的装饰器父类,有两个具体的装饰器:ScrollDecorator给Componet画上滚动条

(简单地在被装饰对象draw()后System.out.print(" drawScroll")即可 )

BorderDecorator给Componet画上边框

(简单地在被装饰对象draw()后System.out.print(" drawBorder");即可 )

解题思路:


1.分析谁是ConcreteDecorator(具体装饰器),谁是ConcreteComponent(基础组件)

2.根据ConcreteDecorator(具体装饰器)定义装饰器父类Decorator

3.根据ConcreteComponent(基础组件)Decorator统一组件行为(这里是draw())得到Component

于是画出类图:

代码附详细注释:

重点:

class ScrollDecorator extends Decorator{ private Component component; public ScrollDecorator(Component component){ this.component=component; } public void draw(){ component.draw(); System.out.print(" drawScroll"); } } class BorderDecorator extends Decorator{ private Component component; public BorderDecorator(Component component){ this.component=component; } public void draw(){ component.draw(); System.out.print(" drawBorder"); } }

对里面的一些代码进行说明:

装饰器的装饰:

1.对基础组件进行装饰

2.对被装饰过的组件进行继续装饰的行为(如装了滚动条还要装边框的情况)

所以有:先画出要装饰的组件情况,再加上自己装饰的内容

public void draw(){ component.draw(); System.out.print(" drawScroll"); }

其他:

/** * 抽象组件类(Component):装饰者模式的顶层抽象 * 定义了所有具体组件(如TextBox、Table)和装饰者(Decorator)的统一接口 * 核心作用是规范组件的绘制行为,为装饰者包装组件提供统一标准 */ abstract class Component { /** * 抽象绘制方法:所有组件和装饰者都必须实现该方法,用于执行具体的绘制逻辑 */ abstract void draw(); } /** * 具体组件类:文本框(TextBox) * 继承自抽象组件Component,实现了具体的绘制逻辑,是被装饰者包装的核心对象 */ class TextBox extends Component { /** * 实现文本框的绘制逻辑 * 输出文本框绘制的标识信息 */ @Override void draw() { System.out.print("drawTextBox"); } } /** * 具体组件类:表格(Table) * 继承自抽象组件Component,实现了具体的表格绘制逻辑,是被装饰者包装的核心对象 */ class Table extends Component { /** * 实现表格的绘制逻辑 * 输出表格绘制的标识信息 */ @Override void draw() { System.out.print("drawTable"); } } /** * 抽象装饰者类(Decorator):继承自Component,是所有具体装饰者的父类 * 核心作用是持有组件对象(被装饰者),并统一装饰者的行为规范,实现对组件的功能扩展 */ abstract class Decorator extends Component { // 持有抽象组件对象,用于包装(装饰)具体组件或其他装饰者(支持多层装饰) protected Component component; /** * 装饰者构造方法:传入需要被装饰的组件对象 * @param component 被装饰的组件(可以是具体组件,也可以是其他装饰者对象) */ public Decorator(Component component) { this.component = component; } } /** * 具体装饰者类:边框装饰者(BorderDecorator) * 继承自抽象装饰者Decorator,用于为组件添加“绘制边框”的额外功能 */ class BorderDecorator extends Decorator { /** * 构造方法:传入需要添加边框装饰的组件 * @param component 被装饰的组件(TextBox/Table或其他装饰者) */ public BorderDecorator(Component component) { super(component); // 调用父类Decorator的构造方法,初始化被装饰组件 } /** * 重写绘制方法:在原有组件绘制逻辑的基础上,添加边框绘制的功能 * 这是装饰者模式的核心:不修改原有组件逻辑,通过包装扩展功能 */ @Override void draw() { // 1. 先执行额外的装饰逻辑:绘制边框(前置扩展) System.out.print("drawBorder->"); // 2. 调用被装饰组件的draw方法,执行原有核心绘制逻辑 component.draw(); } } /** * 具体装饰者类:滚动条装饰者(ScrollDecorator) * 继承自抽象装饰者Decorator,用于为组件添加“绘制滚动条”的额外功能 */ class ScrollDecorator extends Decorator { /** * 构造方法:传入需要添加滚动条装饰的组件 * @param component 被装饰的组件(TextBox/Table或其他装饰者) */ public ScrollDecorator(Component component) { super(component); // 调用父类Decorator的构造方法,初始化被装饰组件 } /** * 重写绘制方法:在原有组件(或已装饰组件)绘制逻辑的基础上,添加滚动条绘制功能 * 支持多层装饰嵌套(如先给Table加边框,再给带边框的Table加滚动条) */ @Override void draw() { // 1. 先执行额外的装饰逻辑:绘制滚动条(前置扩展) System.out.print("drawScroll->"); // 2. 调用被装饰组件的draw方法,执行其原有逻辑(可能是核心组件逻辑或其他装饰者逻辑) component.draw(); } } /** * 主类:程序入口,用于测试装饰者模式的使用 * 演示如何通过装饰者为具体组件添加多层额外功能 */ public class Main{ /** * 主方法:程序执行入口 * @param args 命令行参数(本程序未使用) */ public static void main(String[] args){ // 1. 多层装饰:先给Table添加边框装饰,再给带边框的Table添加滚动条装饰 // 最终得到一个“带滚动条+带边框”的Table组件 Component table=new ScrollDecorator(new BorderDecorator(new Table())); // 2. 单层装饰:给TextBox添加边框装饰,得到一个“带边框”的TextBox组件 Component text=new BorderDecorator(new TextBox()); // 3. 调用装饰后的Table组件的绘制方法,会依次执行滚动条→边框→Table的绘制逻辑 table.draw(); // 换行:用于分隔两个组件的输出结果,提升可读性 System.out.println(); // 4. 调用装饰后的TextBox组件的绘制方法,会依次执行边框→TextBox的绘制逻辑 text.draw(); } }

测试:

/** * 主类:程序入口,用于测试装饰者模式的使用 * 演示如何通过装饰者为具体组件添加多层额外功能 */ public class Main{ /** * 主方法:程序执行入口 * @param args 命令行参数(本程序未使用) */ public static void main(String[] args){ // 1. 多层装饰:先给Table添加边框装饰,再给带边框的Table添加滚动条装饰 // 最终得到一个“带滚动条+带边框”的Table组件 Component table=new ScrollDecorator(new BorderDecorator(new Table())); // 2. 单层装饰:给TextBox添加边框装饰,得到一个“带边框”的TextBox组件 Component text=new BorderDecorator(new TextBox()); // 3. 调用装饰后的Table组件的绘制方法,会依次执行滚动条→边框→Table的绘制逻辑 table.draw(); // 换行:用于分隔两个组件的输出结果,提升可读性 System.out.println(); // 4. 调用装饰后的TextBox组件的绘制方法,会依次执行边框→TextBox的绘制逻辑 text.draw(); } }

三,练习

Java IO 流的设计使用了装饰器设计模式,例如字符流输入流抽象类Reader 中有方法 public abstract int read() 读取一个字符 ; StringRead是具体的字符输入流,实现read()方法,从字符串中读取一个字符。FilterReader是抽象的装饰器类。请从FilterReader 类继承实现 LowerCaseStringReader ,把输入字符流中大写字母都转换为小写。

只需要 补充完成 LowerCaseStringReader 类,且仅需提交 LowerCaseStringReader 类即可

题目给出:

class LowerCaseStringReader extends FilterReader { Reader in; protected LowerCaseStringReader(Reader in) { super(in); this.in=in; } @Override public int read() throws IOException { /* 请补充代码 */ } } public class Main{ public static void main(String[] args) throws IOException { LowerCaseStringReader r=new LowerCaseStringReader(new StringReader("Design Pattern")); int c; while( (c=r.read())>0){ System.out.print((char)c); } } }
装饰器模式核心角色本题对应的 Java IO 类 / 实现角色说明
Component(抽象组件)Reader抽象类所有字符输入流(基础组件 + 装饰者)的顶层统一接口,定义了核心方法read()(读取一个字符),规范了所有字符输入流的行为标准
ConcreteComponent(具体基础组件)StringReader继承自Reader,是被装饰的核心对象(无任何额外功能扩展,仅实现基础业务逻辑),负责从字符串中读取原始字符,不做任何转换处理
Decorator(抽象装饰者)FilterReader1. 必须继承自抽象组件Reader(保证和基础组件具有统一接口,外部使用时无需区分 “基础组件” 和 “装饰者”);2. 内部持有Reader类型的引用(可指向基础组件或其他装饰者,支持多层装饰);3. 本身是抽象类,不实现具体的扩展逻辑,仅作为所有具体装饰者的父类
ConcreteDecorator(具体装饰者)LowerCaseStringReader类(本题需要实现的类)1. 继承自抽象装饰者FilterReader;2. 持有被装饰的Reader对象(通过构造方法传入);3. 重写Reader的核心方法read(),在原有基础组件(StringReader)的read()方法基础上,添加 “大写字母转小写” 的扩展功能,这是装饰器模式的核心实现

需要的题目代码如下

public int read() throws IOException { // 1. 先调用被装饰对象(in,本质是StringReader)的read()方法,获取原始字符 int originalChar = in.read(); // 2. 判断字符是否有效(Reader的read()方法返回-1表示读取到流末尾) if (originalChar == -1) { return -1; // 到达流末尾,直接返回-1 } // 3. 将原始字符转为char类型,判断是否为大写字母 char ch = (char) originalChar; if (ch >= 'A' && ch <= 'Z') { // 大写字母转为小写:ASCII码中,大写字母+32对应小写字母 return Character.toLowerCase(ch); // 等价于:return (char) (ch + 32); } // 4. 非大写字母,直接返回原始字符 return originalChar; }

四,总结

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

装饰器模式通过将对象包装在装饰器类中,以便动态地修改其行为。

这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

设计模式系列持续更新,欢迎关注博主~

希望对大家有用,祝您开心~(o゜▽゜)o☆,有问题欢迎交流,俺会改的✊

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/25 13:48:31

智谱Open-AutoGLM究竟有多强?:3大核心技术解密国产AutoML新范式

第一章&#xff1a;智谱 Open-AutoGLM沉思在大模型与自动化机器学习交汇的前沿&#xff0c;智谱推出的 Open-AutoGLM 引发了广泛的技术关注。它并非传统意义上的 AutoML 工具&#xff0c;而是尝试将自然语言理解能力与自动化建模流程深度融合&#xff0c;实现以“对话”驱动机器…

作者头像 李华
网站建设 2025/12/25 13:42:39

(AutoGLM 2.0 vs 传统建模):性能对比实测,结果令人震惊

第一章&#xff1a;AutoGLM 2.0 vs 传统建模&#xff1a;性能对比实测&#xff0c;结果令人震惊在真实业务场景中对 AutoGLM 2.0 与传统机器学习建模流程进行端到端对比测试&#xff0c;结果显示其效率与精度均实现跨越式提升。本次测试基于金融风控数据集&#xff0c;涵盖特征…

作者头像 李华
网站建设 2025/12/25 13:41:15

29、Git Hooks与项目组合策略详解

Git Hooks与项目组合策略详解 1. 引言 在使用Git进行版本控制的过程中,我们经常会有各种特定的需求,比如在执行某些操作前后自动执行特定任务,或者处理项目中依赖的外部库。Git提供了钩子(Hooks)机制来满足前者的需求,同时对于项目组合,也有多种策略可供选择。 2. Gi…

作者头像 李华
网站建设 2025/12/25 13:40:55

8个降AI率工具推荐!本科生高效降aigc神器

8个降AI率工具推荐&#xff01;本科生高效降aigc神器 AI降重工具&#xff1a;论文写作的隐形助手 随着人工智能技术的不断发展&#xff0c;越来越多的本科生在论文写作中开始使用AI辅助工具。然而&#xff0c;这些工具生成的内容往往带有明显的AI痕迹&#xff0c;导致AIGC率过高…

作者头像 李华
网站建设 2025/12/25 13:36:12

PDM系统:跨部门角色设计与流程对接的核心逻辑

在现代制造体系中&#xff0c;产品数据管理&#xff08;PDM&#xff09;系统已成为驱动跨部门协作的核心平台。其价值远不止于技术工具&#xff0c;更在于通过清晰的角色架构、流程与权限设计&#xff0c;打破组织壁垒&#xff0c;实现高效协同。一次常规的材料替换流程&#x…

作者头像 李华
网站建设 2025/12/27 1:36:31

8、时间处理与信号处理:C语言在UNIX系统中的应用

时间处理与信号处理:C语言在UNIX系统中的应用 1. 时间表示与转换 在C语言的UNIX系统编程中,时间的表示和转换是常见的操作。首先,我们有一个 tm 结构体来表示时间的各个部分: struct tm {int tm_sec; /* seconds 0-59 */int tm_min; /* min…

作者头像 李华