深入探索Java设计模式(三)之装饰器模式
抽丝剥茧 细说架构那些事——【优锐课】
装饰器模式使你可以在运行时使用类似于对象组成的技术来装饰类。这在我们希望实例化具有新职责的对象而无需对基础类进行任何代码更改的情况下尤其有用。本文是在学习完优锐课JAVA架构VIP课程—【框架源码专题】中《学习源码中的优秀设计模式》后写下的学习感悟。探讨了这种模式,并向你展示了如何使用提供的Java代码示例来实现它。
总览
装饰器模式是“四人帮”(Erich Gamma,Richard Helm,Ralph Johnson,John Vlissides)建立的结构设计模式之一。 通过解决在运行时向对象添加新状态或行为的反复出现的问题,它在面向对象的设计中利用了可重用性和灵活性。尽管这种想法与面向对象原理(称为继承)押韵,但简单继承在这种情况下不适用,因为它是静态的并且考虑到整个类。这为新方法铺平了道路,因为它着重于提供灵活的替代方法来扩展子类功能,因此可以动态地向对象施加新的责任。
装饰器模式
顾名思义,装饰器模式可配置特定对象的功能。这是Java原始IO类中的一种常见模式,用于对JVM之外的源进行读写。例如,InputStream和OutputStream类及其子类在其读取和写入操作中广泛使用此模式。可以链接这些类的实现,以有效地从不同的源(例如本机文件系统)读取和写入数据。
例如,请注意抽象类OutputStream。它有一个称为read的抽象方法,该方法必须由子类定义。可以重写该方法以扩展其行为,以更改或增强其效率。在将职责委派给另一个OutputStream之前,OutputStream实现会执行所需的工作。实现链将另一个OutputStream用作构造函数参数。具体的子类,例如OutputStream的FileOutputStream或SocketOutputStream,是管道的末尾,最终写入数据,而没有将写入责任委托给另一个流。因此,在其构造函数参数中不需要另一个OutputStream对象。
让我们看看在Java IO类的OutputStream类中使用装饰器模式如何导致在将字节数组写入磁盘之前将多个操作链接在一起。
@Test
public void testingDecoratorPattern() throws IOException {
final File file = new File("myfile.dat");
final FileOutputStream fileOutputStream = new
FileOutputStream(f);
final BufferedOutputStream bufferedOutputStream = new
BufferedOutputStream(fileOutputStream);
final ObjectOutputStream objectOutputStream = new
ObjectOutputStream(fileOutputStream);
objectOutputStream.writeBoolean(true);
objectOutputStream.writeInt(12);
objectOutputStream.writeObject(new ArrayList<Integer>());
objectOutputStream.flush();
objectOutputStream.close();
bufferedOutputStream.close();
fileOutputStream.close();
assertTrue(file.exists());
}
FileOutputStream对象用于将文件写入磁盘。 BufferedOutputStream对象缓存对写操作的所有调用,并一次写入几个字节。 这可以提高效率,特别是在写入磁盘时。ObjectOutputStream中的对象序列化的内置机制将对象和原始类型写入流中。但是,ObjectOutputStream不知道将文件写入何处。这主要用于将责任委托给另一个OutputStream。
装饰器模式的使用
假设我们要创建一个类设计,但要增加新功能。 在这种情况下,装饰器模式可为客户端提供所需的功能组合,以增强进一步的实现,如图1所示。

图1:装饰器模式
在这里,茶是一个抽象类,由产品的所有类别或变体子类化。在包含有关其类型的特定信息的每个子类中都设置了detailsinstance变量。getDetails()方法返回有关其类型的信息。父类将price() 方法声明为抽象,子类将定义其自己的实现。除了可用的茶类型以外,我们还可以通过多种变体和组合实现任意数量的茶。这是装饰器模式的关键。
实现装饰器模式
现在,让我们看看如何实现装饰器模式。该示例非常简单,不言自明。这些类的布局如下。
package org.mano.example;
public interface Car {
void paint();
} package org.mano.example;
public class ElectricCar implements Car {
@Override
public void paint() {
// ...
}
} package org.mano.example;
public class HybridCar implements Car {
@Override
public void paint() {
// ...
}
} package org.mano.example;
public abstract class CarDecorator implements Car {
protected Car decoratedCar;
public CarDecorator(Car car){
decoratedCar = car;
}
public void paint(){
decoratedCar.paint();
}
} package org.mano.example;
public class CarColorDecorator extends CarDecorator {
public CarColorDecorator(Car car) {
super (car);
}
@Override
public void paint(){
decoratedCar.paint();
setTheme(decoratedCar);
}
private void setTheme(Car car){
// ...
} } package org.mano.example;
public class DPApp {
public static void main(String[] args) {
Car defaultHybridCar = new HybridCar();
Car redHybridCar = new CarColorDecorator(new
HybridCar());
Car blueElectricCar = new CarColorDecorator(new
ElectricCar());
defaultHybridCar.paint();
redHybridCar.paint();
blueElectricCar.paint();
}
}
结论
这是OOP中最常用的模式之一。这种模式的强大之处在于将对象组合在一起,例如ObjectOutputStream,BufferedOutputStream和FileOutputStream扩展了抽象超类OutputStream。每个子类构造函数都将OutputStream对象作为参数。没有装饰器模式,这将是不可能的。否则,我们必须创建许多类来获取本质,这将是一个糟糕的设计。
感谢阅读!欢迎留言。想更深入探讨学习也欢迎私信我。下篇继续~

深入探索Java设计模式(三)之装饰器模式的更多相关文章
- 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...
- Java设计模式12:装饰器模式
装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...
- JAVA设计模式之【装饰者模式】
JAVA设计模式之[装饰者模式] 装饰模式 对新房进行装修并没有改变房屋的本质,但它可以让房子变得更漂亮.更温馨.更实用. 在软件设计中,对已有对象(新房)的功能进行扩展(装修). 把通用功能封装在装 ...
- 设计模式PHP篇(三)————装饰器模式
简单的用php实现了装饰器模式: <?php /** *简单的装饰器模式 */ class PrintText { protected $decorators = []; public func ...
- 设计模式(三)——装饰器模式(Decorator Pattern)
发现太过于刻意按照计划来写博客,有点不实际,刚好最近在一个网课上复习AOP的知识,讲到了装饰器模式和代理模式,顺便复习总结一下. 首先了解一下装饰器模式,从名字里面可以看出来,装饰器模式就类似于房子装 ...
- Java IO流以及装饰器模式在其上的运用
流概述 Java中,流是一种有序的字节序列,可以有任意的长度.从应用流向目的地称为输出流,从目的地流向应用称为输入流. Java的流族谱 Java的 java.io 包中囊括了整个流的家族,输出流和输 ...
- 设计模式学习心得<装饰器模式 Decorator>
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装 ...
- 设计模式のDecoratorPattern(装饰器模式)----结构模式
一.产生背景 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装 ...
- 设计模式入门之装饰器模式Decorator
//装饰模式定义:动态地给一个对象加入一些额外的职责. //就添加功能来说.装饰模式比生成子类更为灵活 //这也提现了面向对象设计中的一条基本原则,即:尽量使用对象组合,而不是对象继承 //Compo ...
- java进阶系列之装饰器模式
1.介绍 装饰器模式顾名思义就是装饰某个对象的,是一种结构型模式.装饰器模式允许向一个现有对象添加新的功能,同时不改变其结构,用户可以随意的扩展原有的对象.它是作为现有的类的一个包装.装饰器模式一方面 ...
随机推荐
- 搭建Nginx七层反向代理
基于https://www.cnblogs.com/Dfengshuo/p/11911406.html这个基础上,在来补充下七层代理的配置方式.简单理解下四层和七层协议负载的区别吧,四层是网络层,负载 ...
- CentOS 7下配置ISO镜像文件为本地yum源
环境限制外网怎么办?离线环境怎么解决依赖?yum源配起来,可以解决大部分包的安装^_^ 环境: 虚拟机:VMware Workstation Pro 12.x Linux系统版本:CentOS-7-x ...
- 攻略前端面试官(一):JS的数据类型和内存机制浅析
原文地址:http://rainykane.cn/2019/09/29/与K_K君一起攻略前端面试官(一):JS的数据类型和内存机制浅析/ 背就完事了 介绍:一些知识点相关的面试题和答案 使用姿势:看 ...
- C#-面向对象:争议TDD(测试驱动开发)
----------------------- 绝对原创!版权所有,转发需经过作者同意. ----------------------- 在谈到特性的使用场景时,还有一个绝对离不开的就是 单元测试 按 ...
- Java工作流引擎全局变量的介绍
关键词:工作流快速开发平台 工作流流设计 业务流程管理 asp.net 开源工作流bpm工作流系统 java工作流主流框架 自定义工作流引擎 在系统中有很多的地方需要用到表达式的地方,这些 ...
- mysql插入的时间莫名的加一秒
1.问题描述 我获取当天最大的时间: public static Date getEndOfDay(Date date) { LocalDateTime localDateTime = LocalDa ...
- 【Android - 问题解决】之Android Studio在Refreshing Gradle Project卡住的问题
今天把Android Studio从2.2版本升级到了2.3版本,但是再打开以前项目的时候,就卡在 “Refreshing XXX Gradle Project” 这里不动了. 网上搜了一些解决方案, ...
- 远程连接mysql出现1045错误的解决办法
第一步:停止MySQL服务 第二步:在你MySQL的安装目录下找到my.ini,文件,打开文件查找到 [mysqld] ,在其下方添加上一行 skip-grant-tables,然后保存. 第三步:启 ...
- Linux发展历史(简略)
LINUX UNIX历史发展 1969肯 汤姆森在DEC PDP-7机器上开发出了UNIX系统 1971肯 汤姆森的同事丹尼斯 里奇发明了C语言 1973UNIX系统绝大部分用C语言重写,为提高UNI ...
- PAT(甲级)2019年秋季考试
第一题用搜索,超时了,待补 更新第一题思路 dfs + 剪枝,首先确定 n的最后一位数字肯定是9,为什么呢,因为 任意两个相邻的数肯定互为质数(gcd=1),所以 n 的末尾肯定是9,这样n+1产生的 ...