【设计模式】结构型设计模式之 从IO流设计思想来看装饰器模式

2024-06-10 09:36

本文主要是介绍【设计模式】结构型设计模式之 从IO流设计思想来看装饰器模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

介绍

装饰器模式也称为包装模式(Wrapper Pattern) 是指在不改变原有对象的基础之上,将功能附加到对象上,提供了比继承更有弹性的替代方案(扩展原有对象的功能),属于结构型模式。
装饰器模式的核心是功能扩展,使用装饰器模式可以透明且动态地扩展类的功能。

装饰器模式代码举例

实现逻辑

  1. 装饰器类和原始类实现共同的父类,下方案例中的 Coffe
  2. 装饰器类,组合原始类的对象作为目标对象
  3. 装饰器类重写需要装饰的方法,并且重写的内容中可以调用原始类的对象方法。
  4. 通过中间层的装饰器基类,避免实现每个共同父类的方法

代码

//装饰器和目标类基础接口
public interface Coffee {String getDescription();double getCost();
}//具体的咖啡,什么都不加
public class SimpleCoffee implements Coffee {@Overridepublic String getDescription() {return "Simple Coffee";}@Overridepublic double getCost() {return 1.0;}
}//装饰器基类,为了避免每个装饰器都要手动重新实现共同父类的接口,即使该装饰器不需要装饰对应方法
public abstract class CoffeeDecorator implements Coffee {protected Coffee decoratedCoffee;public CoffeeDecorator(Coffee coffee) {this.decoratedCoffee = coffee;}@Overridepublic abstract String getDescription();@Overridepublic double getCost() {return decoratedCoffee.getCost();}
}//摩卡咖啡装饰器,增加风味描述、增加价格
public class MochaDecorator extends CoffeeDecorator {public MochaDecorator(Coffee coffee) {super(coffee);}@Overridepublic String getDescription() {return decoratedCoffee.getDescription() + ", Mocha";}@Overridepublic double getCost() {return super.getCost() + 0.5;}
}//奶油装饰器,增加奶油、增加价格
public class WhipDecorator extends CoffeeDecorator {public WhipDecorator(Coffee coffee) {super(coffee);}@Overridepublic String getDescription() {return decoratedCoffee.getDescription() + ", Whip";}@Overridepublic double getCost() {return super.getCost() + 0.3;}
}//测试类
public class Main {public static void main(String[] args) {// 创建一杯简单的咖啡Coffee simpleCoffee = new SimpleCoffee();// 添加摩卡装饰Coffee mochaCoffee = new MochaDecorator(simpleCoffee);// 再添加奶泡装饰Coffee finalCoffee = new WhipDecorator(mochaCoffee);System.out.println(finalCoffee.getDescription() + " costs $" + finalCoffee.getCost());}
}
Simple Coffee, Mocha, Whip costs $1.8

IO 类库的装饰器模式

为什么没有 BufferdFileInputStream

在 JAVA 的 IO 类库中,例如如果让 FileInputStream 支持 BufferdInputStream,需要让 需要间接的将 FileInputStream 传递给 BufferdInputStream。为什么 Java 不直接支持BufferdFileInputStream 呢。

InputStream in = new FileInputStream("");
InputStream bin = new BufferedInputStream(in);

为什么不基于继承实现 BufferedFileInputStream

  1. 如果 InputStream 类只有一个子类 FileInputStream 那么再在 FileInputStream 下面实现一个BufferedInputStream 也没有什么问题
  2. 问题在于 InputStream 的子类太多了,如果每个子类都单独实现 Buffered 功能和 DataInputStream 的功能那么类的数量将会爆炸性增多。

IO 类库使用装饰模式实现

  1. 在设计原则中,组合优于继承,针对继承结构过于复杂的问题可以将继承关系转换为组合关系来解决。
  2. 所以 IO 类库中,对于 BufferedInputStream 没有选择对所有的 InputStream 实现一遍,而是只实现一遍通过组合目标 InputStream 来实现增强功能
  3. 对于需要实现 Buffered 的功能的 inputStream,只需使用BufferedInputStream 对其进行一次包装即可实现。
  4. 并且如果想要实现 DataInputStream 的按照数据类型读取,只需要再次添加一层包装即可。

总结&思考

总结

  1. 装饰器模式可以解决继承关系过于复杂的问题,通过组合关系替代继承关系。
  2. 装饰器模式主要的作用是给原始类添加增强功能,除此之外装饰器模式还支持嵌套使用,为了满足这个功能装饰器类和原始类都继承自相同的父类或者接口。
  3. 装饰器模式和静态代理模很相似,都是通过组合来对原始类进行增强,主要区别是代理模式主要对原始类不相关的功能进行增强,但是装饰器模式是对原始类相关功能的增强。

IO 类库的 FilterInputStream 的作用是什么

  1. 和案例中的装饰类基类作用一样,提供 InputStream 需要实现的方法的实现。方法的具体执行通过委托给组合的 InputStream 对象实现。
  2. 如果没有 FilterInputStream,那么每个装饰器类,都需要对 InputStream 的方法提供实现,即使是委托给组合的 InputStream 成员对象执行也会很麻烦。

装饰器类和原始类有相同的父类的作用

装饰器类和原始类有相同的父类,例如 InputStream 和 Coffee 可以实现对原始类进行“嵌套”多个装饰器类来进行增强。例如对 FileInputStream 包装 BufferedInputStream 后再包装一层 DataInputStream,这样既实现了缓存读取又实现类按照基本数据类型来读取。

和其他组合代替继承的设计模式(例如代理模式)的区别

代理模式中,代理类附加的是原始类不相关的功能,但是装饰器模式中附加的是与原始类相关的增强功能。

这篇关于【设计模式】结构型设计模式之 从IO流设计思想来看装饰器模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1047804

相关文章

MyBatis设计SQL返回布尔值(Boolean)的常见方法

《MyBatis设计SQL返回布尔值(Boolean)的常见方法》这篇文章主要为大家详细介绍了MyBatis设计SQL返回布尔值(Boolean)的几种常见方法,文中的示例代码讲解详细,感兴趣的小伙伴... 目录方案一:使用COUNT查询存在性(推荐)方案二:条件表达式直接返回布尔方案三:存在性检查(EXI

如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socket read timed out的问题

《如何解决Druid线程池Cause:java.sql.SQLRecoverableException:IO错误:Socketreadtimedout的问题》:本文主要介绍解决Druid线程... 目录异常信息触发场景找到版本发布更新的说明从版本更新信息可以看到该默认逻辑已经去除总结异常信息触发场景复

RabbitMQ工作模式中的RPC通信模式详解

《RabbitMQ工作模式中的RPC通信模式详解》在RabbitMQ中,RPC模式通过消息队列实现远程调用功能,这篇文章给大家介绍RabbitMQ工作模式之RPC通信模式,感兴趣的朋友一起看看吧... 目录RPC通信模式概述工作流程代码案例引入依赖常量类编写客户端代码编写服务端代码RPC通信模式概述在R

SQL Server身份验证模式步骤和示例代码

《SQLServer身份验证模式步骤和示例代码》SQLServer是一个广泛使用的关系数据库管理系统,通常使用两种身份验证模式:Windows身份验证和SQLServer身份验证,本文将详细介绍身份... 目录身份验证方式的概念更改身份验证方式的步骤方法一:使用SQL Server Management S

Python文件操作与IO流的使用方式

《Python文件操作与IO流的使用方式》:本文主要介绍Python文件操作与IO流的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、python文件操作基础1. 打开文件2. 关闭文件二、文件读写操作1.www.chinasem.cn 读取文件2. 写

Redis高可用-主从复制、哨兵模式与集群模式详解

《Redis高可用-主从复制、哨兵模式与集群模式详解》:本文主要介绍Redis高可用-主从复制、哨兵模式与集群模式的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝... 目录Redis高可用-主从复制、哨兵模式与集群模式概要一、主从复制(Master-Slave Repli

一文带你搞懂Redis Stream的6种消息处理模式

《一文带你搞懂RedisStream的6种消息处理模式》Redis5.0版本引入的Stream数据类型,为Redis生态带来了强大而灵活的消息队列功能,本文将为大家详细介绍RedisStream的6... 目录1. 简单消费模式(Simple Consumption)基本概念核心命令实现示例使用场景优缺点2

Python装饰器之类装饰器详解

《Python装饰器之类装饰器详解》本文将详细介绍Python中类装饰器的概念、使用方法以及应用场景,并通过一个综合详细的例子展示如何使用类装饰器,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录1. 引言2. 装饰器的基本概念2.1. 函数装饰器复习2.2 类装饰器的定义和使用3. 类装饰

Nginx location匹配模式与规则详解

《Nginxlocation匹配模式与规则详解》:本文主要介绍Nginxlocation匹配模式与规则,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、环境二、匹配模式1. 精准模式2. 前缀模式(不继续匹配正则)3. 前缀模式(继续匹配正则)4. 正则模式(大

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子