网站建设经,wordpress自动化框架,上海网站建设网页,层次化网络设计的优点是什么#x1f4e2; 大家好#xff0c;我是 【战神刘玉栋】#xff0c;有10多年的研发经验#xff0c;致力于前后端技术栈的知识沉淀和传播。 #x1f497; #x1f33b; CSDN入驻不久#xff0c;希望大家多多支持#xff0c;后续会继续提升文章质量#xff0c;绝不滥竽充数… 大家好我是 【战神刘玉栋】有10多年的研发经验致力于前后端技术栈的知识沉淀和传播。 CSDN入驻不久希望大家多多支持后续会继续提升文章质量绝不滥竽充数欢迎多多交流。 文章目录 写在前面的话基础介绍代码实现Spring 使用装饰者模式动态代理VS装饰者模式装饰者模式的简化总结陈词 写在前面的话
上一篇文章《程序猿之设计模式实战 · 策略模式》介绍的了策略模式的实际运用这篇紧随其后补充上装饰者模式。
装饰者模式也是相当实用的适合很多场景且听慢慢道来。 基础介绍
基础概念
装饰者模式是一种结构型设计模式它允许在不改变对象自身的情况下动态地给对象添加新的功能。通过将功能封装在装饰类中装饰者模式提供了一种灵活的方式来扩展对象的行为。
装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任。换言之客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不使用创造更多子类的情况下将对象的功能加以扩展。
类图 组成部分
装饰者模式通常由以下几个部分组成
1、组件接口Component定义一个接口声明具体组件和装饰者都需要实现的方法。
2、具体组件ConcreteComponent定义一个将要接收附加责任的类实现组件接口表示被装饰的对象。
3、装饰者Decorator也是实现组件接口的类持有一个组件对象的引用并在其方法中调用该组件的方法。装饰者可以在调用前后添加额外的功能。
4、具体装饰者ConcreteDecorator继承自装饰者类具体实现添加的功能。
常用场景
装饰者模式适用于以下场景
1、需要动态添加功能当你希望在运行时为对象添加功能而不影响其他对象时。
2、避免子类爆炸当功能组合的数量较多时使用装饰者模式可以避免创建大量的子类。
3、增强类的功能当你希望在不修改现有类的情况下增强类的功能。 代码实现
示例以文本输出添加粗体、斜体的职责为例。
Step1、定义组件接口
public interface Text {String getContent();
}Step2、定义具体组件
public class BaseText implements Text {private final String content;public BaseText(String content) {this.content content;}Overridepublic String getContent() {return content;}
}Step3、定义装饰者
public abstract class TextDecorator implements Text {protected Text text;public TextDecorator(Text text) {this.text text;}
}Step4、定义具体装饰者
public class BoldTextDecorator extends TextDecorator {public BoldTextDecorator(Text text) {super(text);}Overridepublic String getContent() {return b text.getContent() /b;}
}public class ItalicTextDecorator extends TextDecorator {public ItalicTextDecorator(Text text1) {super(text1);}Overridepublic String getContent() {return i text.getContent() /i;}
}Step5、客户端测试
public class DecoratorClient {public static void main(String[] args) {Text plainText new BaseText(Hello, 战神!);// 添加粗体装饰Text boldTextDecorator new BoldTextDecorator(plainText);System.out.println(boldTextDecorator.getContent());// 输出内容// bHello, 战神!/b// 添加斜体装饰Text italicTextDecorator new ItalicTextDecorator(boldTextDecorator);System.out.println(italicTextDecorator.getContent());// 输出内容// ibHello, 战神!/b/i}
}点评一下
从代码看还是挺清晰的各司其职。
可以理解为不影响原有功能动态进行功能的增强就是装饰者模式。
特别适合解决例如购物、点餐、SKU等组合的情况即容易出现“类爆炸”的场合。 Spring 使用装饰者模式
在 Spring 框架中装饰者模式被广泛应用于以下几个方面
1、AOP面向切面编程
Spring AOP 使用代理模式来实现切面功能实际上可以看作是对目标对象的装饰。通过在目标对象周围添加切面逻辑如事务管理、日志记录等而不改变目标对象的代码。
2、Spring MVC 的 HandlerInterceptor
在 Spring MVC 中HandlerInterceptor 可以被视为一种装饰者模式的实现。它允许在请求处理的不同阶段如请求前、请求后添加额外的处理逻辑而不需要修改控制器本身的代码。
3、BeanPostProcessor
Spring 的 BeanPostProcessor 接口允许在 Spring 容器创建和初始化 bean 之后添加额外的功能或修改 bean 的属性。这种机制也可以看作是对 bean 的装饰。
总结装饰者模式是一种灵活的设计模式允许在运行时动态地为对象添加功能。在 Spring 框架中装饰者模式的思想被广泛应用于 AOP、拦截器和 bean 处理等多个方面使得功能的扩展变得更加灵活和可维护。 动态代理VS装饰者模式
相似之处
细心的伙伴可能观察到日常接触的动态代理是否装饰者模式虽然有相似之处。
1、从增强功能上看两者都可以在不修改原有类的情况下为对象添加额外的功能或行为。
2、从代码结构上看都涉及到对原有对象的封装通常通过组合或代理的方式来实现。
但其实两者还是存在区别
1、实现方式
装饰者模式通常通过创建一个装饰者类来包装原有对象装饰者类实现与原有对象相同的接口并在其方法中调用原有对象的方法同时添加新的行为。
动态代理使用反射机制在运行时创建一个代理对象该代理对象可以在方法调用时添加额外的逻辑。动态代理不需要创建具体的装饰类而是通过代理类来增强功能。
2、使用场景
装饰者模式适用于需要在多个地方以不同方式增强对象的场景通常是为了增加对象的功能。
动态代理适用于需要在运行时决定增强逻辑的场景比如 AOP面向切面编程中的横切关注点。
3、灵活性
装饰者模式需要在编译时确定装饰的组合通常是静态的。
动态代理可以在运行时动态决定增强的逻辑具有更高的灵活性。
总结一下
动态代理可以被视为一种特殊的装饰者模式实现但它更侧重于运行时的动态性和灵活性而装饰者模式则更关注于通过组合来增强对象的功能。因此虽然它们有相似的目的但在实现和使用上有明显的区别。 装饰者模式的简化
实际开发中往往场景不会都是这么复杂没这么多元素此时可以考虑简化。 Tips实战要灵活学会变通而不要一味追求标准、套用标准。 如果只有一个待装饰的类ConcreteComponent那么可以考虑去掉抽象的 Component 类接口把Decorator作为一个ConcreteComponent子类。 如果只有一个ConcreteDecorator类那么就没有必要建立一个单独的Decorator类而可以把Decorator和ConcreteDecorator的责任合并成一个类。 是不是很简洁不过怎么越看越像JDK动态代理
万变不如其宗根源应该靠面向接口编程以及持有被代理/装饰的对象吧。 总结陈词
还是那句话不用过多的纠结在用的是哪个设计模式实现的是什么标准。
遇到实际问题能使用合适的方式解决同时代码经得起推敲和扩展才是最主要的。
回到装饰者模式常用于解决“类爆炸”的问题动态附加功能同时基本满足面向对象开发原则的全部原则。
不过装饰模式也有相应的缺点由于使用装饰模式可以比使用继承关系需要较少数目的类。使用较少的类当然使设计比较易于进行。但是在另一方面使用装饰模式会产生比使用继承关系更多的对象。更多的对象会使得查错变得困难特别是这些对象看上去都很相像。
当然装饰者还是很强的遇到适合的场景果断用上缺点可以忽略不计。
还是那句话你可以不用但不能不会。 后续会逐步分享企业实际开发中的实战经验有需要交流的可以联系博主。