【设计模式】快速理解装饰者模式,及其在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再做一些功能上的增强,很巧妙的实现了在不必改变原类文件情况下,允许向一个现有的对象添加新的功能。


(五)总结


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



相关文章
|
1月前
|
设计模式 PHP
PHP中的设计模式:单一职责原则在软件开发中的应用
【10月更文挑战第8天】 在软件开发中,设计模式是解决常见问题的经验总结,而单一职责原则作为面向对象设计的基本原则之一,强调一个类应该只有一个引起变化的原因。本文将探讨单一职责原则在PHP中的应用,通过实际代码示例展示如何运用该原则来提高代码的可维护性和可扩展性。
33 1
|
10天前
|
设计模式 Java Kotlin
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
|
18天前
|
设计模式 存储 数据库连接
PHP中的设计模式:单例模式的深入理解与应用
【10月更文挑战第22天】 在软件开发中,设计模式是解决特定问题的通用解决方案。本文将通过通俗易懂的语言和实例,深入探讨PHP中单例模式的概念、实现方法及其在实际开发中的应用,帮助读者更好地理解和运用这一重要的设计模式。
14 1
|
1月前
|
设计模式 PHP 开发者
PHP中的设计模式:桥接模式的解析与应用
在软件开发的浩瀚海洋中,设计模式如同灯塔一般,为开发者们指引方向。本文将深入探讨PHP中的一种重要设计模式——桥接模式。桥接模式巧妙地将抽象与实现分离,通过封装一个抽象的接口,使得实现和抽象可以独立变化。本文将阐述桥接模式的定义、结构、优缺点及其应用场景,并通过具体的PHP示例代码展示如何在实际项目中灵活运用这一设计模式。让我们一起走进桥接模式的世界,感受它的魅力所在。
|
29天前
|
设计模式 测试技术 持续交付
架构视角下的NHibernate:设计模式与企业级应用考量
【10月更文挑战第13天】随着软件开发向更复杂、更大规模的应用转变,数据访问层的设计变得尤为重要。NHibernate作为一个成熟的对象关系映射(ORM)框架,为企业级.NET应用程序提供了强大的支持。本文旨在为有一定经验的开发者提供一个全面的指南,介绍如何在架构层面有效地使用NHibernate,并结合领域驱动设计(DDD)原则来构建既强大又易于维护的数据层。
37 2
|
1月前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的深入解析与应用
【10月更文挑战第8天】 在软件开发的浩瀚宇宙中,设计模式如同星辰指引,照亮了代码设计与架构的航道。本文旨在深入探索PHP语境下策略模式(Strategy Pattern)的精髓,不仅剖析其内核原理,还将其融入实战演练,让理论在实践中生根发芽。策略模式,作为解决“如何优雅地封装算法族”的答案,以其独特的灵活性与扩展性,赋予PHP应用以动态变换行为的能力,而无需牵动既有的类结构。
23 2
|
24天前
|
设计模式 Java Kotlin
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
39 0
|
24天前
|
设计模式 开发者 Python
Python编程中的设计模式应用与实践###
【10月更文挑战第18天】 本文深入探讨了Python编程中设计模式的应用与实践,通过简洁明了的语言和生动的实例,揭示了设计模式在提升代码可维护性、可扩展性和重用性方面的关键作用。文章首先概述了设计模式的基本概念和重要性,随后详细解析了几种常用的设计模式,如单例模式、工厂模式、观察者模式等,在Python中的具体实现方式,并通过对比分析,展示了设计模式如何优化代码结构,增强系统的灵活性和健壮性。此外,文章还提供了实用的建议和最佳实践,帮助读者在实际项目中有效运用设计模式。 ###
13 0
|
1月前
|
设计模式 Java Kotlin
Kotlin 学习笔记- 改良设计模式 - 装饰者模式
Kotlin 学习笔记- 改良设计模式 - 装饰者模式
26 0
|
1月前
|
设计模式 Java Kotlin
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
Kotlin教程笔记(56) - 改良设计模式 - 装饰者模式
22 0