当前位置: 首页 > news >正文

【设计模式】装饰器模式(结构型)⭐⭐

文章目录

  • 1.概念
    • 1.1 什么是装饰器模式
    • 1.2 优点与缺点
  • 2.实现方式
  • 3. Java 哪些地方用到了装饰器模式
  • 4. Spring 哪些地方用到了装饰器模式

1.概念

1.1 什么是装饰器模式

它允许用户在不修改现有对象的代码的情况下向对象添加新的功能;这种模式是通过创建一个包含该对象的包装对象来实现的,从而扩展该对象的功能。

1.2 优点与缺点

优点:
1.灵活性和扩展性:装饰器模式允许在运行时向对象添加新的行为,提供了比继承更大的灵活性。
2.遵守开闭原则:装饰器模式允许向系统添加新的行为而不需要修改现有代码,这符合开闭原则(软件实体应该对扩展开放,对修改关闭)。
3.代码复用:装饰器可以被多个对象共享,这减少了代码的重复,提高了代码复用性。
4.对象功能增强:在不改变原有对象的情况下,可以有选择性地增强对象的功能。
5.组合优于继承:装饰器模式使用对象组合而不是继承来扩展功能,这有助于避免继承层次可能带来的复杂性和脆弱性。
缺点:
1.增加复杂性:装饰器模式可能会增加系统的复杂性,因为需要创建多个小对象来表示不同的功能。2.调试困难:由于装饰器可以嵌套使用,调试和理解运行时的行为可能会变得更加困难。
3.性能问题:装饰器模式可能会引入额外的性能开销,因为需要创建额外的对象,并且可能需要通过多个装饰器来解析方法调用。
4.设计复杂:如果使用不当,装饰器模式可能会导致设计变得复杂,特别是当装饰器之间的关系变得复杂时。
5.接口限制:装饰器模式要求装饰器和被装饰的对象实现相同的接口,这在某些情况下可能是不切实际的。

2.实现方式

①定义接口

public interface Beverage {String getDescription();double cost();
}

②创建一个实现了Beverage接口的具体类SimpleCoffee

public class SimpleCoffee implements Beverage {@Overridepublic String getDescription() {return "Simple Coffee";}@Overridepublic double cost() {return 1.0;}
}

③定义一个装饰器类CondimentDecorator,它也实现了Beverage接口,并持有一个Beverage对象的引用:

public abstract class CondimentDecorator implements Beverage {protected Beverage beverage;public CondimentDecorator(Beverage beverage) {this.beverage = beverage;}public abstract String getDescription();
}

④创建具体的装饰器类,比如Milk、Sugar和Chocolate,它们都扩展了CondimentDecorator并添加了各自的成本和描述:

public class Milk extends CondimentDecorator {public Milk(Beverage beverage) {super(beverage);}@Overridepublic String getDescription() {return beverage.getDescription() + ", Milk";}@Overridepublic double cost() {return beverage.cost() + 0.5;}
}public class Sugar extends CondimentDecorator {public Sugar(Beverage beverage) {super(beverage);}@Overridepublic String getDescription() {return beverage.getDescription() + ", Sugar";}@Overridepublic double cost() {return beverage.cost() + 0.1;}
}public class Chocolate extends CondimentDecorator {public Chocolate(Beverage beverage) {super(beverage);}@Overridepublic String getDescription() {return beverage.getDescription() + ", Chocolate";}@Overridepublic double cost() {return beverage.cost() + 0.3;}
}

⑤ 使用

public class DecoratorDemo {public static void main(String[] args) {Beverage coffee = new SimpleCoffee();System.out.println(coffee.getDescription() + " $" + coffee.cost());coffee = new Milk(coffee);coffee = new Sugar(coffee);coffee = new Chocolate(coffee);System.out.println(coffee.getDescription() + " $" + coffee.cost());}
}

3. Java 哪些地方用到了装饰器模式

Java I/O 流
Java的I/O库广泛使用了装饰器模式来增强基本输入输出流的功能。例如,BufferedInputStream和BufferedOutputStream类通过装饰基本的InputStream和OutputStream来提供缓冲功能。同样,DataInputStream和DataOutputStream为基本的流添加了读写基本数据类型的能力。
Java Servlet API
Java Servlet API中的HttpServletRequestWrapper和HttpServletResponseWrapper类允许开发者通过装饰原始的HttpServletRequest和HttpServletResponse对象来添加或修改功能。
Java动态代理
Java的动态代理机制允许在运行时创建一个实现了一组接口的代理类实例。这个代理实例实际上是一个装饰器,它可以在不修改原始对象代码的情况下,为原始对象添加新的行为,如事务管理、日志记录等。
Spring框架
Spring框架在很多地方使用了装饰器模式,例如在AOP(面向切面编程)中,Spring会创建代理对象来包装目标对象,以实现事务管理、权限检查等横切关注点的功能。
Apache Commons IO
Apache Commons IO库提供了一些装饰器类,如ProxyInputStream和ProxyOutputStream,这些类可以用来创建自定义的流装饰器。
JDBC
JDBC驱动程序有时会使用装饰器模式来增强或修改原始的Connection、Statement或ResultSet对象的行为。
JAX-RS
JAX-RS(Java API for RESTful Web Services)中的客户端API允许使用装饰器模式来增强或修改Client、WebTarget、Invocation等对象的行为。

4. Spring 哪些地方用到了装饰器模式

AOP(面向切面编程):
Spring AOP允许通过声明式方式添加横切关注点(如日志记录、事务管理、安全检查等)到目标对象。Spring创建代理对象来包装目标对象,这些代理对象在调用目标方法前后执行额外的代码。这实际上是一种装饰器模式的应用,它允许在不修改目标对象代码的情况下增强其行为。
事务管理
在Spring中,事务管理通常是通过AOP实现的。Spring可以为目标方法创建一个代理,该代理在方法执行前后管理事务的开启和关闭,而无需修改目标方法的代码。
Spring Security
Spring Security使用方法拦截器来实现安全控制。它可以为目标方法创建代理,这些代理在方法执行前检查用户的权限,如果用户没有足够的权限,则不允许执行目标方法。
Spring Data JPA
Spring Data JPA中的仓库(Repository)可以通过自定义的实现来扩展。开发者可以创建一个自定义的仓库实现,并通过Spring的配置将其与标准仓库接口关联起来。这实际上是在使用装饰器模式来扩展仓库的功能。
Spring WebFlux
Spring WebFlux中的WebFilter和WebExceptionHandler可以被视为装饰器模式的应用。它们允许在请求处理的各个阶段添加额外的处理逻辑,而不需要修改原始的处理器代码。
Spring Cloud
在Spring Cloud中,装饰器模式被用于实现服务断路器、负载均衡等功能。例如,Hystrix断路器可以通过装饰原始的服务调用逻辑来添加断路器功能,从而在服务调用失败时提供备选方案。
Spring Boot
Spring Boot自动配置的原理也可以看作是装饰器模式的一种应用。Spring Boot可以自动配置各种组件,如数据源、事务管理器等,这些自动配置的组件可以被用户的自定义配置所增强或覆盖。

http://www.lryc.cn/news/367881.html

相关文章:

  • 计算机网络--应用层
  • 计算机网络 —— 网络层(IP数据报)
  • Clo3D导出服装动画,使用Unity3D展示
  • LSTM 词语模型上的动态量化
  • STM32 proteus + STM32Cubemx仿真教程(第一课LED教程)
  • 享元模式
  • R语言数据分析16-针对芬兰污染指数的分析与考察
  • Search用法Python:深入探索搜索功能的应用与技巧
  • STM32的FreeRtos的学习
  • 从零入手人工智能(2)——搭建开发环境
  • Web前端指南
  • AI菜鸟向前飞 — LangChain系列之十七 - 剖析AgentExecutor
  • nodejs 第三方库 exiftool-vendored
  • docker部署redis实践
  • Web前端学习之路:深入探索学习时长与技能进阶的奥秘
  • 如何不用命令创建用户
  • 基于Python实现可视化分析中国500强排行榜数据的设计与实现
  • VUE3 学习笔记(13):VUE3 下的Element-Plus基本使用
  • MySql数据库安全加固
  • Nginx(title小图标)修改方法
  • iOS 17.5中的一个漏洞
  • 如何在 iPhone 上恢复已删除的短信
  • 矩阵练习1
  • 【C++ | 拷贝赋值运算符函数】一文了解C++的 拷贝赋值运算符函数
  • Linux网络安全
  • Django 视图类
  • 【Java面试】十七、并发篇(上)
  • 七天进阶elasticsearch[one]
  • 全新抖音快手小红书视频解析去水印系统网站源码
  • 图解 Python 编程(12) | 文件和编码方式