设计模式之装饰器模式

 

前言

上一篇文章中,分享了适配器模式的一些相关知识,在本篇文章将为大家分享装饰器模式,乍一听,适配器和装饰器,是不是有点类似的感觉?其实这两种模式,完全是两种不同的设计模式,下面就开始正题吧,如果我的分享内容对你有用,请关注我的微信公众号吧,后续会持续输出更多的干货内容的哦!

什么是装饰器模式

装饰器模式是一种结构型设计模式,它允许向一个现有的对象动态添加功能,而不需要修改其源代码。这种模式的核心思想是使用装饰器类来包装原始类,并在保持类方法签名完整性的前提下,提供额外的功能。每个装饰器都包装了原始组件,并添加了新的功能。这些装饰器可以被嵌套,以实现更多的功能组合。使用装饰器模式的好处之一是在运行时动态添加或删除功能,而不会对原始组件的代码产生影响。这种灵活性使得装饰器模式非常适用于大型项目中的代码重构和维护。

装饰器模式的核心角色

装饰器模式的核心角色包括:

  1. 抽象组件(Component):这是一个接口或者抽象类,它定义了原始对象的基本行为。装饰器模式要求这个接口或抽象类能够被装饰器类和具体组件类共享。
  2. 具体组件(Concrete Component):这是被装饰的原始对象,它实现了抽象组件定义的行为。
  3. 抽象装饰器(Decorator):这是一个继承自抽象组件的类,它持有一个抽象组件对象,并定义了与抽象组件相同的接口。抽象装饰器类通过组合方式持有其他装饰器对象,它可以向抽象组件添加新的功能。
  4. 具体装饰器(Concrete Decorator):这是实现了抽象装饰器的类,它负责向抽象组件添加新的功能。通常,具体装饰器会在调用原始对象的方法之前或之后执行自己的操作。

这些核心角色共同实现了装饰器模式的主要功能,即在保持原始对象行为不变的同时,动态地添加新的功能。

在Java中,适配器模式如何实现?

假如在做一个管理飞机的程序,要展示飞机的特性,应该怎么设计这个程序呢?如果使用装饰器模式,是这样的:

/*** 抽象组件:飞机*/
public abstract class Aircraft {public String type;public Aircraft(String type) {this.type = type;}abstract void show();}
public class OrdinaryAircraft extends Aircraft {public OrdinaryAircraft(String type) {super(type);}@Overridepublic void show() {System.out.println("型号:"+super.type);System.out.println("基础特性:飞行");}
}

如果是战斗机呢,除了飞行外,还要具备在空中战斗的能力,当然具备空中战斗能力的飞机种类有很多,比如歼击机、轰炸机、预警机、直升机等,而且后续还有新的型号补发明出来,这就要求程序在设计的时候要有足够的扩展性,使用装饰器模式很简单:

1、定义一个抽象飞机类;

2、定义一个抽象的战斗机,持有抽象飞机类;

3、普通飞机类继承了抽象飞机类,就具备了飞机的基础特性,战斗机最基础的特性也必须能飞行,所以持有一个抽象飞机类,除了战斗机本身的一些特性外,也就拥有了普通飞机的飞行的特性;

4、J15A、J20、WZ10等种型号的飞机继承了抽象战斗机类,就同时拥有了飞行的特性和战斗的特性;当然不同的战斗机的战斗特性不相同,这就是具体的战斗机类中实现就行了;

5、后续再新增其他型号的战斗机,就新增具体的战斗机类并继承抽象战斗机类,完全符合开闭原则;

public abstract class Fighter  {protected Aircraft aircraft;public Fighter(Aircraft aircraft) {this.aircraft = aircraft;}abstract void show();
}
/*** 战斗机:歼20*/
public class J20 extends Fighter {public J20(Aircraft aircraft) {super(aircraft);}@Overridepublic void show() {super.aircraft.show();System.out.println("优势特性:空中格斗专家");}
}
/*** 歼15A型战机*/
public class J15A extends Fighter{public J15A(Aircraft aircraft) {super(aircraft);}@Overridevoid show() {super.aircraft.show();System.out.println("优势特性:短距起飞/低空突防");}
}
/*** 武直10武装直升机*/
public class WZ10 extends Fighter{public WZ10(Aircraft aircraft) {super(aircraft);}@Overridevoid show() {super.aircraft.show();System.out.println("优势特性:树梢杀手");}
}
/*** 装饰器模式*/
public class Test7 {public static void main(String[] args) {Aircraft ordinaryAircraft = new OrdinaryAircraft("普通飞机");ordinaryAircraft.show();System.out.println("---------------");Fighter j20 = new J20(new OrdinaryAircraft("歼20战机"));j20.show();System.out.println("---------------");Fighter j15A=new J15A(new OrdinaryAircraft("歼15A型战机")) ;j15A.show();System.out.println("---------------");Fighter wz10=new WZ10(new OrdinaryAircraft("武直10武装直升机"));wz10.show();}
}

装饰器在Spring中的应用

装饰器模式在Spring中有很多应用,主要可以用来动态地给一个对象增加一些额外的职责,即动态地给一个对象穿上衣服。

  1. 装饰器模式允许向一个现有的对象添加新的功能,同时又不改变其结构。在Spring中,这种特性被广泛应用,例如在Spring Session中,使用装饰器模式对原生的HttpSession进行增强,可以将在分布式session中同步session数据的需求通过扩展其功能的方式“装饰”在原有的HttpSession对象上。
  2. 另一个应用是在处理HTTP请求时,Spring Session框架使用HTTP请求包装类(如SessionRepositoryRequestWrapper)和Session存储过滤器(如SessionRepositoryFilter)实现。这种方式使用了装饰器模式,以在请求前后加入特定的行为,达到在运行时动态使用、撤销功能的效果。

装饰器的应用场景

装饰器模式在很多场景中都有应用,比如:

  1. 用于扩展类的功能,可以动态地给对象添加或撤销功能,比如日志记录、缓存处理等。
  2. 在软件系统中,可以通过装饰器模式方便地为各个类或方法添加日志记录功能,而不需要修改原有的代码。
  3. 应用于需要进行缓存处理的场景,可以在方法调用时检查缓存是否存在计算结果,如果存在则直接返回,否则进行计算并将结果存入缓存,以提高系统的响应速度。

总结

优点:

  1. 动态扩展功能:装饰器模式可以在运行时动态地给对象添加或删除功能,而不需要修改原有的代码。
  2. 灵活性和可扩展性:装饰器模式可以灵活地组合和扩展类的功能,可以根据需要添加或删除装饰器,从而改变对象的行为。
  3. 代码的可读性和可维护性:装饰器模式可以将多个装饰器组合在一起,形成一个复杂的对象行为,使得代码更加清晰、可读性更好,同时也可以方便地维护和修改代码。

缺点:

  1. 实现复杂度较高:装饰器模式需要在原有的类上添加一个接口,并在接口中定义了和原有类相同的方法,同时还需要实现一个装饰器类来扩展原有类的功能,这使得代码实现起来较为复杂。
  2. 可能会引入过多的装饰器类:装饰器模式可以灵活地扩展类的功能,但是也可能会引入过多的装饰器类,使得代码变得冗余和复杂。
  3. 可能会影响性能:装饰器模式需要在运行时动态地创建对象和调用方法,这可能会影响系统的性能。

总的来说,装饰器模式是一种灵活的设计模式,可以方便地扩展类的功能,但是也需要注意实现复杂度和性能问题。

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

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

相关文章

GoLong的学习之路(一)语法之变量与常量

目录 GoLang变量批量声明变量的初始化类型推导短变量声明匿名变量 常量iota(特殊)(需要重点记忆) GoLang go的诞生为了解决在21世纪多核和网络化环境越来越复杂的变成问题而发明的Go语言。 go语言是从Ken Thomepson发明的B语言和…

外网nat+nat server,内网做路由过滤,以及ppp CHAR认证 企业网搭建

作业 网络拓扑图如下所示: 要求:做适当的截图,表示完成相应的操作。 按照网络拓扑要求搭建网络结构,按照个人学号配置每个节点的IP地址,其中X为班级号,Y为学号末尾2位;Y1为学号末尾2位1&#…

Seata学习

Seata Seata 是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务。 官网地址:https://seata.io/zh-cn/index.html 为什么会产生分布式事务? 示例:用户下单后需要创建订单,同时…

高通Quick Charge快速充电原理分析

1 三段式AC充电器 涓流、恒流、恒压。 2 QC 2.0 2.1 高通Quick Charge 2.0 快速充电原理分析 QC 2.0快速充电需要手机端和充电器都支持才行。 当将充电器端通过数据线连到手机上时,充电器默认的是将D和D-短接的,这样手机端探测到的充电器类型是DCP&#…

网络编程 day3

#include <head.h> #define SER_PORT 6678 //服务器端口号 #define SER_IP "192.168.115.64"//服务器IP地址 #define CLI_PORT 6666 //客户端端口号 #define CLI_IP "192.168.115.93" int main(int argc, const char *argv[]) {//1.创建套接字,用于连…

structs2 重构成SpringBoot架构

structs2 重构成SpringBoot架构 目录参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,wait for change,challenge Survive. happy for hardess to solve den…

分类预测 | MATLAB实现SSA-CNN-GRU-Attention数据分类预测(SE注意力机制)

分类预测 | MATLAB实现SSA-CNN-GRU-Attention数据分类预测&#xff08;SE注意力机制&#xff09; 目录 分类预测 | MATLAB实现SSA-CNN-GRU-Attention数据分类预测&#xff08;SE注意力机制&#xff09;分类效果基本描述模型描述程序设计参考资料 分类效果 基本描述 1.MATLAB实现…

Java将djvu文件转成pdf

需求来源 迫于有部分资源是djvu格式的文件&#xff0c;需要预览这部分文件&#xff0c;web端无法直接预览djvu&#xff0c;所以需要将djvu转成pdf。 转换方法 简单来说就是先把djvu文件转换成tiff文件&#xff0c;再将tiff文件转换成pdf文件。 Ubuntu服务器 如果服务器是U…

数据库管理-第112期 Oracle Exadata 03-网络与ILOM(20231020)

数据库管理-第112期 Oracle Exadata 03-网络与ILOM&#xff08;202301020&#xff09; 在Exadata中&#xff0c;除了对外网络以外&#xff0c;其余网络都是服务于一体机内部各组件的网络&#xff0c;本期对这些网络的具体情况和硬件管理相关做一个讲解。 1 网络分类 1.1 生产…

Tinywebserve学习之linux 用户态内核态

一.CPU指令集权限 指令集是实现CPU实现软件指挥硬件执行的媒介&#xff0c;具体来说每一条汇编语句都对应了一条CPU指令&#xff0c;而非常多的CPU指令再一起组成一个甚至多个集合&#xff0c;指令的集合叫CPU指令集&#xff1b; 因为CPU指令集可以操纵硬件&#xff0c;会造成…

读书笔记之《敏捷测试从零开始》(一)

大家好&#xff0c;我是rainbowzhou。 子曰&#xff1a;学而时习之&#xff0c;不亦说乎&#xff1f;今天我想和大家分享一本测试书籍——《敏捷测试从零开始》。以下为我的读书笔记&#xff1a; 精彩片段摘录&#xff1a; 焦虑往往来自于对比&#xff0c;当你在自己的圈子里面…

Python如何对数据进行排序和排名操作?

目录 一、使用sorted()函数进行排序 二、使用数组模块的sort()函数进行排序 三、使用pandas库进行排序和排名 四、使用numpy库进行排序和排名 五、使用matplotlib库进行数据可视化 总结 在Python中&#xff0c;对数据进行排序和排名是数据处理中非常常见的操作。下面我们…

【嵌入式开源库】timeslice的使用,完全解耦的时间片轮询框架构

完全解耦的时间片轮询框架构 简介项目代码timeslice.htimeslice.clist.hlist.c 创建工程移植代码实验函数说明timeslice_task_inittimeslice_task_addtimeslice_tak_deltimeslice_get_task_num 结尾 简介 timeslice是一个时间片轮询框架&#xff0c;他是一个完全解耦的时间片轮…

LSTM 与 GRU

RNN无法处理长距离依赖问题&#xff0c;通俗点就是不能处理一些较长的序列数据&#xff0c;那么今天就来介绍一下两个能处理长距离依赖问题地RNN变种结构&#xff0c;LSTM和GRU。 1. LSTM&#xff08;Long short-term memory&#xff09; 1.1 LSTM结构 上左图是普通RNN结构图…

Nginx详细配置指南

nginx.conf配置 找到Nginx的安装目录下的nginx.conf文件&#xff0c;该文件负责Nginx的基础功能配置。 配置文件概述 Nginx的主配置文件(conf/nginx.conf)按以下结构组织&#xff1a; 配置块功能描述全局块与Nginx运行相关的全局设置events块与网络连接有关的设置http块代理…

Django和jQuery,实现Ajax表格数据分页展示

1.需求描述 当存在重新请求接口才能返回数据的功能时&#xff0c;若页面的内容很长&#xff0c;每次点击一个功能&#xff0c;页面又回到了顶部&#xff0c;对于用户的体验感不太友好&#xff0c;我们希望当用户点击这类的功能时&#xff0c;能直接加载到数据&#xff0c;请求…

Towards a Rigorous Evaluation of Time-series Anomaly Detection(论文翻译)

1 Introduction 随着工业4.0加速系统自动化&#xff0c;系统故障的后果可能会产生重大的社会影响&#xff08;Baheti和Gill 2011; Lee 2008; Lee&#xff0c;Bagheri和Kao 2015&#xff09;。为了防止这种故障&#xff0c;检测系统的异常状态比以往任何时候都更加重要&#xff…

同为科技(TOWE)大功率带机械联锁工业插头插座箱

所谓工业机械联锁开关插座&#xff0c;是一种工业用途插座&#xff0c;带有一个旋钮开关&#xff0c;通过旋钮开关可以控制电源的通断。其特点是具有联动锁定机构&#xff0c;当旋钮开关断开操作后&#xff0c;联动锁定机构会自动撤销限位&#xff0c;使插头能够插入或拔出。当…

LVS+keepalive高可用集群

keepalive简介 keepalive为LVS应用延伸的高可用服务。lvs的调度器无法做高可用。但keepalive不是为lvs专门集群服务的&#xff0c;也可以为其他的的代理服务器做高可用。 keepalive在lvs的高可用集群&#xff0c;主调度器和备调度器(可以有多个) 一主两备或一主一备。 VRRP: k…

Mysql视图特性用户管理

目录 一、视图基本使用 二、用户管理 2.1 用户 ①用户信息 ②创建用户 tips:(解决无法创建用户) ③删除用户 ④修改用户密码 2.2数据库的权限 ①给用户授权 ②回收权限 视图&#xff1a;视图是一种虚拟表。视图是基于一个或多个基础表中的数据所创建的一个查询结果…