从原理到实践:装饰器模式如何在项目中落地详解(给原对象增加新的行为和功能)
装饰器模式---- 不修改原始对象,给原对象增加新的行为和功能。
2.1、概念
装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许动态地向对象添加额外的功能,而无需修改其原始代码。核心思想是可以动态地为对象添加额外的功能,而不需要修改对象本身的代码。这个模式中,我们通过创建一个装饰器类来包装某个具体的组件实现,并增加一些额外的功能。由于装饰器类与被装饰者实现了相同的接口,因此它可以替代被装饰者,并且可以在运行时动态地为被装饰者添加额外的功能。
装饰器模式的核心思想是基于组合的方式实现功能的扩展,它与继承相比,更加灵活和可扩展。通过使用装饰器模式,我们可以避免对原始对象进行修改,并能够动态地为对象添加新的功能,从而使得软件设计更加灵活和易于维护。
2.2、实现代码
下面是Java中装饰器模式的简单实现:
// 定义组件接口
public interface Component {void operation();
}// 具体组件实现类
public class ConcreteComponent implements Component {
@Override
public void operation() {System.out.println("执行具体组件操作");
}
}// 装饰器类
public class Decorator implements Component {private Component component; // 维持对被装饰者对象的引用public Decorator(Component component) {this.component = component;}@Overridepublic void operation() {component.operation(); // 调用被装饰者对象的方法}
}// 具体装饰器类A
public class ConcreteDecoratorA extends Decorator {public ConcreteDecoratorA(Component component) {super(component);}@Overridepublic void operation() {super.operation(); // 调用父类的方法System.out.println("为具体组件A增加额外功能");}
}// 具体装饰器类B
public class ConcreteDecoratorB extends Decorator {public ConcreteDecoratorB(Component component) {super(component);}@Overridepublic void operation() {super.operation(); // 调用父类的方法System.out.println("为具体组件B增加额外功能");}
}
在上面的示例中,我们首先定义了一个Component接口和一个ConcreteComponent实现类,后者提供了基础的功能。然后,我们定义了一个Decorator装饰器类,并在其中包装了一个Component类型的引用,该类实现了Component接口并提供了与被装饰者相同的行为。
接下来,我们又定义了两个具体装饰器类ConcreteDecoratorA和ConcreteDecoratorB,这两个类分别向原始的ConcreteComponent组件添加不同的额外功能。
最后,我们可以通过如下代码使用装饰器模式:
Component component = new ConcreteComponent();
Component decoratorA = new ConcreteDecoratorA(component);
Component decoratorB = new ConcreteDecoratorB(decoratorA);
decoratorB.operation();
在这个示例中,我们首先创建了一个ConcreteComponent实例,并将其作为参数传递给装饰器类ConcreteDecoratorA和ConcreteDecoratorB。最后,我们调用了decoratorB的operation方法,它会依次调用ConcreteDecoratorA、ConcreteDecoratorB和ConcreteComponent的operation方法,从而实现了多个功能的组合。通过装饰器模式,我们可以实现动态地向对象添加额外的功能,这样可以让代码更加灵活和可扩展。但是需要注意,如果装饰器过多或者过于复杂,可能会导致代码难以维护。
2.3、如何落地
2.3.1、拦截器中的实现
装饰器模式一般的使用场景:例如在运行时给原方法添加日志、缓存、权限控制、安全认证及监控等。
在Spring MVC项目中,装饰器模式通常用于实现拦截器(Interceptor)功能。拦截器是一种常见的AOP技术,它可以在处理请求之前或之后执行某些操作。
下面是一个简单的示例代码,演示了如何使用装饰器模式实现Spring MVC中的拦截器功能:
首先,定义一个接口HandlerInterceptor作为被装饰者,它包含三个方法:preHandle、postHandle和afterCompletion,这些方法分别对应请求处理前、请求处理后和请求完成后的操作。
public interface HandlerInterceptor {boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception;void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception;
}
然后,定义一个抽象类HandlerInterceptorDecorator作为装饰器类,它继承自HandlerInterceptor接口并添加了一个protected类型的成员变量decorated,该变量表示被装饰的对象。此外,该类还提供了一个构造函数,用于初始化成员变量。
public abstract class HandlerInterceptorDecorator implements HandlerInterceptor {protected HandlerInterceptor decorated;public HandlerInterceptorDecorator(HandlerInterceptor decorated) {this.decorated = decorated;}
}
接着,我们可以定义一些具体的装饰器类,例如SecurityInterceptor、LoggingInterceptor和PerformanceMonitorInterceptor,这些类都继承自HandlerInterceptorDecorator类,并重写了父类中的方法以提供额外的功能。
public class SecurityInterceptor extends HandlerInterceptorDecorator {public SecurityInterceptor(HandlerInterceptor decorated) {super(decorated);}@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 在请求处理前执行安全检查return super.preHandle(request, response, handler);}
}public class LoggingInterceptor extends HandlerInterceptorDecorator {public LoggingInterceptor(HandlerInterceptor decorated) {super(decorated);}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {// 在请求处理后记录日志super.postHandle(request, response, handler, modelAndView);}
}public class PerformanceMonitorInterceptor extends HandlerInterceptorDecorator {public PerformanceMonitorInterceptor(HandlerInterceptor decorated) {super(decorated);}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 在请求完成后记录性能统计信息super.afterCompletion(request, response, handler, ex);}
}
最后,在Spring MVC配置文件中,我们可以将多个拦截器按顺序组合起来,并将它们应用于特定的请求路径:
<mvc:interceptors><bean id="securityInterceptor" class="com.example.SecurityInterceptor"><constructor-arg ref="loggingInterceptor"/></bean><bean id="loggingInterceptor" class="com.example.LoggingInterceptor"><constructor-arg ref="performanceMonitorInterceptor"/></bean><bean id="performanceMonitorInterceptor" class="com.example.PerformanceMonitorInterceptor"><constructor-arg ref="defaultHandlerInterceptor"/></bean><bean id="defaultHandlerInterceptor" class="org.springframework.web.servlet.handler.HandlerInterceptorAdapter"/>
</mvc:interceptors>
在这个示例中,我们首先创建了多个装饰器类,例如SecurityInterceptor、LoggingInterceptor和PerformanceMonitorInterceptor,它们都继承自HandlerInterceptorDecorator并重写了父类中的方法以提供额外的功能。然后,我们通过Spring MVC配置文件将这些拦截器按顺序组合起来,并将它们应用于特定的请求路径。通过使用装饰器模式,我们可以实现动态地为对象添加新的功能,从而让代码更加灵活和可扩展。
2.3.2、InputStream中的实现
以下是InputStream、BufferedInputStream和DataInputStream的源代码分析,以展示它们是如何使用装饰器模式来扩展InputStream类的功能。
InputStream类
InputStream是一个抽象类,它提供了从输入源读取字节的方法。以下是InputStream类的源代码片段:
public abstract class InputStream implements Closeable {public abstract int read() throws IOException;public int read(byte b[], int off, int len) throws IOException {// ...}public long skip(long n) throws IOException {// ...}public int available() throws IOException {// ...}public void close() throws IOException {// ...}
}
FilterInputStream类
FilterInputStream类,它是所有装饰器类的基类,该类继承自InputStream类。以下是FilterInputStream类的源代码片段:
public class FilterInputStream extends InputStream {protected volatile InputStream in;protected FilterInputStream(InputStream in) {this.in = in;}public int read() throws IOException;public int read(byte b[], int off, int len) throws IOException {// ...}public long skip(long n) throws IOException {// ...}public int available() throws IOException {// ...}public void close() throws IOException {// ...}
}
FilterInputStream类是InputStream的一个子类,并且实现了InputStream的所有方法。FilterInputStream类通过装饰器模式来扩展InputStream类的功能,可以在读取数据时对数据进行过滤、处理或包装。
FilterInputStream类的构造函数需要传入一个InputStream对象作为参数,这个InputStream对象是需要被装饰的底层输入流。FilterInputStream类添加了若干个字段和方法,用于扩展InputStream类的功能。
BufferedInputStream类
BufferedInputStream继承自FilterInputStream类,该类本身继承自InputStream类。以下是BufferedInputStream类的源代码片段:
public class BufferedInputStream extends FilterInputStream {protected volatile byte buf[];protected int count;protected int pos;protected int markpos = -1;protected int marklimit;public BufferedInputStream(InputStream in, int size) {super(in);if (size <= 0) {throw new IllegalArgumentException("Buffer size <= 0");}buf = new byte[size];}// ...public synchronized int read() throws IOException {// ...}public synchronized int read(byte[] b, int off, int len)throws IOException {// ...}// ...
}
可以看到,BufferedInputStream将底层的InputStream对象通过构造函数传递进来,并存储在FilterInputStream类中的in字段中。它添加了一个缓存区(buf)和一些额外的状态变量,以实现对数据的预先加载、减少I/O操作次数和提高读取效率的目的。BufferedInputStream的read()方法会先从缓存区中读取数据,如果缓存区为空,则从底层的InputStream对象中读取一定数量的字节并缓存起来。
DataInputStream类
DataInputStream也是一个装饰器模式的实现。以下是DataInputStream类的源代码片段:
public class DataInputStream extends FilterInputStream implements DataInput {// ...public final boolean readBoolean() throws IOException {// ...}public final byte readByte() throws IOException {// ...}public final short readShort() throws IOException {// ...}public final int readInt() throws IOException {// ...}public final long readLong() throws IOException {// ...}public final float readFloat() throws IOException {// ...}public final double readDouble() throws IOException {// ...}public final String readUTF() throws IOException {// ...}// ...
}
可以看到,DataInputStream继承自FilterInputStream类,并添加了额外的方法如readByte,用于将输入流中的数据解码成基本数据类型和字符串。它实现了DataInput接口,该接口定义了许多用于解析二进制数据的方法。DataInputStream的构造函数也需要将底层的InputStream对象传递进来,并存储在FilterInputStream类中的in字段中。
============================================================
如果文章对你有帮助,不要忘记加个关注、点个赞!!!必回关!!!
从原理到实践:装饰器模式如何在项目中落地详解(给原对象增加新的行为和功能)相关推荐
- 装饰器模式在 Collections 类中的应用
我们前面讲到,Java IO 类库是装饰器模式的非常经典的应用.实际上,Java 的 Collections 类也用到了装饰器模式. Collections 类是一个集合容器的工具类,提供了很多静态方 ...
- php设计模式八-----装饰器模式
1.介绍: 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰 ...
- Mybatis源码:Cache 装饰器模式
装饰器模式介绍 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个 ...
- go设计模式之装饰器模式
go设计模式之装饰器模式 再写这篇文章时,我已经看了很多其他人发表的类似文章,大概看了这么多吧. 亓斌的设计模式-装饰者模式(Go语言描述) jeanphorn的Golang设计模式之装饰模式 七八月 ...
- 设计模式笔记十:装饰器模式
原文:http://www.runoob.com/design-pattern/ (大部分摘抄) 少许个人理解,如有错误请指出.欢迎一起讨论. 装饰器模式(Decorator Pattern) 允许向 ...
- 设计模式--装饰器模式
装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装.简单来说,装饰器模式就是 ...
- Java设计模式学习总结(11)——结构型模式之装饰器模式
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装.这种模式创建了一个装饰类,用来包装原 ...
- java设计模式之 装饰器模式
装饰器模式 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构. 这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装 ...
- Java单体应用 - 架构模式 - 03.设计模式-10.装饰器模式
原文地址:http://www.work100.net/training/monolithic-architecture-design-patterns-decorator-pattern.html ...
最新文章
- SpringBoot+Junt+Mock测试方法
- Bdsyn百度手机助手是何物,它是怎样神不知鬼不觉地安装到你的电脑里的?
- Linux 目录配置标准:FHS
- 会c语言如何快速入门python,初学者如何从C语言到Python的转化(北大陈斌老师的举例 )...
- 190709每日一句 以这样的方式去过每一天,你的生活将永远改变!
- 【Labplus 3】Scratch获取角色造型的数量
- python从邻接矩阵计算可达矩阵,复制即用
- matlab图例只显示文字不显示线条
- 微信机器人之PC微信hook
- 逻辑回归算法及其实现
- oeasy教您玩转vim - 43 - # 替换模式
- Power Query零基础入门(Excel2021专业加强版)
- 计算机音乐超级马丽,你与你的音乐梦想,只差一台数学计算器
- CyanogenMod编译
- mysql教学版_MySQL 8从零开始学(视频教学版)
- 爱我所爱,行我所行,听从我心,无问西东
- C语言计算圆柱的表面积 体积
- Dropbox 架设免费个人网站
- c++小游戏大合集(1)
- 计算机导论实验课,《计算机导论》实验课教案
热门文章
- 计算机伦理期末题库2023 免费
- golang环境安装
- DOTA数据集 | retinanet 实验记录(COCO数据格式)
- 渗透测试:ASP/ASPX/JSP/JBoss攻防环境搭建
- java int 128 ==_Integer128==128?false,Integer和int使用==比较的总结
- list和dic区别
- 求助为什么这张图片只显示一条
- 长沙python培训机构培训
- SHELL中的exit 0 和 exit 1有什么区别?
- JavaScript自执行函数,自执行函数是什么,存在的意义?