【设计模式】快速理解装饰者模式,及其在JDK源码中的应用

简介: 装饰者模式(Decorator)的定义是:在不必改变原类文件情况下,允许向一个现有的对象添加新的功能。比如一个毛坯房,可以使用灰色去装饰厨房,可以使用白色装饰客厅,但是不管使用多少颜料去装饰这个房间,房子的本质是不会发现变化的。使用装饰者模式除了可以在不改变原类的前提下装饰对象之外,还可以随意组合各个装饰类,比如有三个装饰类,分别是给原类上红、黄、绿三种颜色。在使用时,可以将任意两种或任意三种装饰类搭配。接下来将会用代码演示上面的这个例子。

(一)什么是装饰者模式


装饰者模式(Decorator)的定义是:在不必改变原类文件情况下,允许向一个现有的对象添加新的功能。比如一个毛坯房,可以使用灰色去装饰厨房,可以使用白色装饰客厅,但是不管使用多少颜料去装饰这个房间,房子的本质是不会发现变化的。


使用装饰者模式除了可以在不改变原类的前提下装饰对象之外,还可以随意组合各个装饰类,比如有三个装饰类,分别是给原类上红、黄、绿三种颜色。在使用时,可以将任意两种或任意三种装饰类搭配。接下来将会用代码演示上面的这个例子。


(二)装饰者模式中的角色


装饰者模式中具备以下四种角色:


Component:一个抽象的组件类,在装饰者模式中扮演着最重要的角色。在给房子上色这个例子中,概念上的房子就是一个Component。如果还不理解,继续往下看。


ConcreteComponent:Component的具体实现,在本次的例子中就是商品房、公寓房等。


Decorator:一个通用的装饰接口或抽象类,内部保存了被装饰的Component对象。

ConcreteDecorator:具体的装饰类,在原类的基础上进行装饰。


(三)装饰者模式案例


原类是房子,可装饰红色、黄色、绿色。接下来的代码就是对这个例子的体现: 首先定义Component,也就是房子抽象类,有一个展示房子的方法:


publicabstractclassHouse {
/*** 展示房子*/publicabstractvoidshow();
}

接下来是ConcreteComponent,抽象房子的实现类,这里定义为商品房,ConcreteComponent可以有很多个:

publicclassCommercialHouseextendsHouse{
@Overridepublicvoidshow() {
System.out.println("这是一个商品房");
    }
}

Decorator是一个通用的抽象类,将房子作为入参传入,并实现同样的show方法

publicclassHouseDecoratorextendsHouse{
privateHousehouse;
publicHouseDecorator(Househouse){
this.house=house;
    }
@Overridepublicvoidshow() {
house.show();
    }
}

ConcreteDecorator具体装饰类定义了三个,分别是红黄蓝装饰:

publicclassRedHouseDecoratorextendsHouseDecorator{
publicRedHouseDecorator(Househouse) {
super(house);
    }
@Overridepublicvoidshow() {
super.show();
System.out.println("装饰了红色");
    }
}
publicclassYellowHouseDecoratorextendsHouseDecorator{
publicYellowHouseDecorator(Househouse) {
super(house);
    }
@Overridepublicvoidshow() {
super.show();
System.out.println("装饰了黄色");
    }
}
publicclassGreenHouseDecoratorextendsHouseDecorator{
publicGreenHouseDecorator(Househouse) {
super(house);
    }
@Overridepublicvoidshow() {
super.show();
System.out.println("装饰了绿色");
    }
}

接下来就是使用了,前面已经提到了,装饰者模式除了可以在不改动原类的情况下增加功能,也可以随意组装各个装饰类:

publicclassMain {
publicstaticvoidmain(String[] args) {
Househouse=newCommercialHouse();
//只装饰红色HouseredHouse=newRedHouseDecorator(house);
redHouse.show();
//装饰绿色和黄色HousegreenAndYellowHouse=newGreenHouseDecorator(newYellowHouseDecorator(house));
greenAndYellowHouse.show();
//三种颜色全部装饰HouseallHouse=newRedHouseDecorator(newGreenHouseDecorator(newYellowHouseDecorator(house)));
allHouse.show();
    }
}

在上面的测试代码中,既可以只有一种颜色的装饰,也可以有两种颜色的装饰,或者是三种颜色的装饰,而原本的商品房这个类没有经过任何修改。如果用继承去实现,每种组装方式都需要新建一个类,装饰者模式的优势就体现出来了。


(四)装饰者模式在源码中的应用


看了很多装饰者模式在源码中的应用,感觉Java.IO中的流在装饰者模式的使用上最经典。以InputStream为例子,InputStream有很多的实现类:


FileInputStream:实现文件的读取。


DataInputStream:读取各种基本数据类型的数据。


BufferedInputStream:可缓存的文件流。


ObjectInputStream:读取对象的文件流。


其他的实现还有很多很多,这里的实现就使用了装饰者模式,保证InputStream不变的前提下,增加其他功能。想象一下,如果要同时实现文件读取和可缓存,那么就可以这样写:


newBufferedInputStream(newFileInputStream(""));

如果想实现基本数据类型读取+文件读取,就可以这样写:

newDataInputStream(newFileInputStream(""));

BufferedInputStream是InputStream子类的子类,在继承关系上,BufferedInputStream继承FilterInputStream,FilterInputStream继承InputStream,这里相当于对装饰类进行了再扩展,看一下FilterInputStream:


publicclassFilterInputStreamextendsInputStream{
protectedvolatileInputStreamin;
protectedFilterInputStream(InputStreamin) {
this.in=in;
    }
publicintread() throwsIOException {
returnin.read();
    }
}

而BufferedInputStream以及DataInputStream都是对FilterInputStream再做一些功能上的增强,很巧妙的实现了在不必改变原类文件情况下,允许向一个现有的对象添加新的功能。


(五)总结


装饰者模式很好地体现了设计模式中的开闭原则,即类应该对扩展开放,对修改关闭。值得深深品味。



相关文章
|
3月前
|
设计模式 人工智能 算法
基于多设计模式的状态扭转设计:策略模式与责任链模式的实战应用
接下来,我会结合实战案例,聊聊如何用「策略模式 + 责任链模式」构建灵活可扩展的状态引擎,让抽奖系统的状态管理从「混乱战场」变成「有序流水线」。
设计模式 存储 人工智能
219 0
|
4月前
|
设计模式 XML 安全
Java枚举(Enum)与设计模式应用
Java枚举不仅是类型安全的常量,还具备面向对象能力,可添加属性与方法,实现接口。通过枚举能优雅实现单例、策略、状态等设计模式,具备线程安全、序列化安全等特性,是编写高效、安全代码的利器。
|
6月前
|
设计模式 存储 缓存
Netty源码—9.性能优化和设计模式
本文主要介绍了Netty的两大性能优化工具、FastThreadLocal的源码和总结、Recycler的设计理念/使用/四个核心组件/初始化/对象获取/对象回收/异线程收割对象和总结,以及Netty设计模式的单例模式和策略模式。
212 53
|
7月前
|
设计模式 缓存 安全
【设计模式】【结构型模式】装饰者模式(Decorator)
一、入门 什么是装饰者模式? 装饰者模式(Decorator Pattern)是 Java 中常用的结构型设计模式,它能在不修改原有对象结构的前提下,动态地为对象添加额外的职责。 为什么要装饰者模式?
170 8
|
9月前
|
设计模式 Java 数据安全/隐私保护
Java 设计模式:装饰者模式(Decorator Pattern)
装饰者模式属于结构型设计模式,允许通过动态包装对象的方式为对象添加新功能,提供比继承更灵活的扩展方式。该模式通过组合替代继承,遵循开闭原则(对扩展开放,对修改关闭)。
|
10月前
|
设计模式 存储 Java
「全网最细 + 实战源码案例」设计模式——责任链模式
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,允许将请求沿着处理者链进行发送。每个处理者可以处理请求或将其传递给下一个处理者,从而实现解耦和灵活性。其结构包括抽象处理者(Handler)、具体处理者(ConcreteHandler)和客户端(Client)。适用于不同方式处理不同种类请求、按顺序执行多个处理者、以及运行时改变处理者及其顺序的场景。典型应用包括日志处理、Java Web过滤器、权限认证等。
215 13
「全网最细 + 实战源码案例」设计模式——责任链模式
|
10月前
|
设计模式 存储 算法
「全网最细 + 实战源码案例」设计模式——命令模式
命令模式(Command Pattern)是一种行为型设计模式,将请求封装成独立对象,从而解耦请求方与接收方。其核心结构包括:Command(命令接口)、ConcreteCommand(具体命令)、Receiver(接收者)和Invoker(调用者)。通过这种方式,命令的执行、撤销、排队等操作更易扩展和灵活。 适用场景: 1. 参数化对象以操作。 2. 操作放入队列或远程执行。 3. 实现回滚功能。 4. 解耦调用者与接收者。 优点: - 遵循单一职责和开闭原则。 - 支持命令组合和延迟执行。 - 可实现撤销、恢复功能。 缺点: - 增加复杂性和类数量。
329 14
「全网最细 + 实战源码案例」设计模式——命令模式
|
10月前
|
设计模式 算法 开发者
「全网最细 + 实战源码案例」设计模式——策略模式
策略模式(Strategy Pattern)是一种行为型设计模式,用于定义一系列可替换的算法或行为,并将它们封装成独立的类。通过上下文持有策略对象,在运行时动态切换算法,提高代码的可维护性和扩展性。适用于需要动态切换算法、避免条件语句、经常扩展算法或保持算法独立性的场景。优点包括符合开闭原则、运行时切换算法、解耦上下文与策略实现、减少条件判断;缺点是增加类数量和策略切换成本。示例中通过定义抽象策略接口和具体策略类,结合上下文类实现动态算法选择。
330 8
「全网最细 + 实战源码案例」设计模式——策略模式
|
10月前
|
设计模式 SQL 算法
「全网最细 + 实战源码案例」设计模式——模板方法模式
模板方法模式是一种行为型设计模式,定义了算法的骨架并在父类中实现不变部分,将可变部分延迟到子类实现。通过这种方式,它避免了代码重复,提高了复用性和扩展性。具体步骤由抽象类定义,子类实现特定逻辑。适用于框架设计、工作流和相似算法结构的场景。优点包括代码复用和符合开闭原则,缺点是可能违反里氏替换原则且灵活性较低。
245 7
「全网最细 + 实战源码案例」设计模式——模板方法模式

热门文章

最新文章