深入探索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.介绍 装饰器模式顾名思义就是装饰某个对象的,是一种结构型模式.装饰器模式允许向一个现有对象添加新的功能,同时不改变其结构,用户可以随意的扩展原有的对象.它是作为现有的类的一个包装.装饰器模式一方面 ...
随机推荐
- 高质量App的架构设计与思考!
最近在做一功能不大.业务也不复杂的小众App,以往做App是发现自己从来没有考虑过一些架构方面的问题,只是按照自己以往的习惯去写代码,忽略了App的设计.本次分享主要包含一些开发App的小经验和技巧, ...
- 【译】利用Lombok消除重复代码
当你在写Getter和Setter时,一定无数次的想过,为什么会有POJO这么烂的东西.你不是一个人!(不是骂人-)无数的开发人员花费了大量的时间来写这种样板代码,而他们本来可以利用这些时间做出更有价 ...
- Win32 COM组件 x Android Service (二)
继续上一篇. 如果不使用AIDL(Android Interface Definition Language接口描述语言)编写服务接口的话,(COM组件,CORBA组件,ICE组件以及其它远程调用框架 ...
- php为什么需要异步编程?php异步编程的详解(附示例)
本篇文章给大家带来的内容是关于php为什么需要异步编程?php异步编程的详解(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 我对 php 异步的知识还比较混乱,写这篇是为了 ...
- GDG Xi'an DevFest 2019 闪电演讲 -《假如我是一个浏览器》PPT(经典多图,建议收藏)
GDG Xi'an DevFest2019演讲PPT链接: http://tmp.link/f/5dd9e6bf461b6 闪电演讲<假如我是一个浏览器>PPT链接: https://gi ...
- UCloud 云服务内容审核 Java 版本实现
前言 最近不少小伙伴反映上传小黄图偶尔性的异常,并且不能上传动态图片,很是苦恼!无她,鉴黄API还没有这么智能,毕竟是自己训练的,不是那么专业!为了更好的服务广大网友,撸主决定接入更加智能快速的鉴黄服 ...
- 宋宝华:关于ARM Linux原子操作的实现
本文系转载,著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 作者: 宋宝华 来源: 微信公众号linux阅码场(id: linuxdev) 竞态无所不在 首先我们要理解竞态(ra ...
- Java8 日期时间API
一.转换 1.与字符串 //LocalDateTime 转 字符串 String str = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss ...
- mac 终端高亮显示~
针对terminal采用bash模式: 编辑 ~/.bash_profile, 加入以下代码: export CLICOLOR=1 export LSCOLORS=gxfxaxdxcxegedabag ...
- Spring Cloud第一篇 | Spring Cloud前言及其常用组件介绍概览
本文是Spring Cloud专栏的第一篇文章,了解本篇文章内容有助于更好的理解后面文章 一.网站架构演变过程 1-1.传统架构 传统的SSH架构,分为三层架构 web控制层.业务逻辑层.数 ...