带你读《2022技术人的百宝黑皮书》——浅析设计模式3 —— 装饰者模式(2)

简介: 带你读《2022技术人的百宝黑皮书》——浅析设计模式3 —— 装饰者模式

带你读《2022技术人的百宝黑皮书》——浅析设计模式3 —— 装饰者模式(1)

https://developer.aliyun.com/article/1262382?groupCode=taobaotech



基本概念

装饰者模式的核心思想是通过创建一个装饰对象(即装饰者),动态扩展目标对象的功能,并且不会改变目标对象 的结构,提供了一种比继承更灵活的替代方案。需要注意的是,装饰对象要与目标对象实现相同的接口,或继承相 同的抽象类;另外装饰对象需要持有目标对象的引用作为成员变量,而具体的赋能任务往往通过带参构造方法来完 成。


下面继续从模式结构和使用步骤两个层面,简单阐述装饰者模式的基本概念。


结构


装饰者模式包含四种类,分别是抽象构件类、具体构件类、抽象装饰者类、具体装饰者类,它们各自负责完成特定 任务,并且相互之间存在紧密联系。

image.png


image.png


使用

有了上述的基本概念,我们将装饰者模式的使用步骤概括为:

1. step1:创建抽象构件类,定义目标对象的抽象类、将要扩展的功能定义成抽象方法;

2. step2:创建具体构件类,定义目标对象的实现类,实现抽象构件中声明的抽象方法;

3. step3:创建抽象装饰者类,维护一个指向抽象构件的引用,并传入构造函数以调用具体构件的实现方法,给具  体构件增加功能;

4. step4:创建具体装饰者类,可以调用抽象装饰者类中定义的方法,并定义若干个新的方法,扩展目标对象的功能。


使用示例

我们在淘宝上购物时,经常会遇到很多平台和商家的优惠活动:满减、聚划算站内的百亿补贴券、店铺折扣等等。 那么在商品自身原价的基础上,叠加了多种优惠活动后,后台应该怎样计算最终的下单结算金额呢?下面就以这种 优惠叠加结算的场景为例,简单分析装饰者模式如何使用。


代码实现

// 定义抽象构件:抽象商品
public interface ItemComponent {
 // 商品价格
 public double checkoutPrice();
}
// 定义具体构件:具体商品
public class ConcreteItemCompoment implements ItemComponent {
 // 原价
 @Override
 public double checkoutPrice() {
 return 200.0;
 }
}
// 定义抽象装饰者:创建传参(抽象构件)构造方法,以便给具体构件增加功能
public abstract class ItemAbsatractDecorator implements ItemComponent {
 protected ItemComponent itemComponent;
 public ItemAbsatractDecorator(ItemComponent myItem) {
 this.itemComponent = myItem;
 }
 @Overrid
 public double checkoutPrice() {
 return this.itemComponent.checkoutPrice();
 }
}
// 定义具体装饰者A:增加店铺折扣八折
public class ShopDiscountDecorator extends ItemAbsatractDecorator {
 public ShopDiscountDecorator(ItemComponent myItem) {
 super(myItem);
 }
  @Override
 public double checkoutPrice() {
 return 0.8 * super.checkoutPrice();
 }
} 
// 定义具体装饰者B:增加满200减20功能,此处忽略判断逻辑
public class FullReductionDecorator extends ItemAbsatractDecorator {
 public FullReductionDecorator(ItemComponent myItem) {
 super(myItem);
 }
  @Override
 public double checkoutPrice() {
 return super.checkoutPrice() - 20;
 }
}
// 定义具体装饰者C:增加百亿补贴券50
public class BybtCouponDecorator extends ItemAbsatractDecorator {
 public BybtCouponDecorator(ItemComponent myItem) {
 super(myItem);
 }
 @Override
 public double checkoutPrice() {
  return super.checkoutPrice() - 50;
 }
}
//客户端调用
public class userPayForItem() {
 public static void main(String[] args) {
 ItemCompoment item = new ConcreteItemCompoment();
 System.out.println("宝贝原价:" + item.checkoutPrice() + " 元");
 item = new ShopDiscountDecorator(item);
 System.out.println("使用店铺折扣后需支付:" + item.checkoutPrice() + " 元");
 item = new FullReductionDecorator(item);
 System.out.println("使用满200减20后需支付:" + item.checkoutPrice() + " 元");
 item = new BybtCouponDecorator(item);
 System.out.println("使用百亿补贴券后需支付:" + item.checkoutPrice() + " 元");
 }
} 


结果输出

宝贝原价:200.0 元
使用店铺折扣后需支付:160.0 元
使用满200减20后需支付:140.0 元
使用百亿补贴券后需支付:90.0 元


UML图


image.png


比较分析  


VS 继承

装饰者模式和继承关系都是要对目标类进行功能扩展,但装饰模式可以提供比继承更多的灵活性:继承是静态添加 功能,在系统运行前就会确定下来;装饰者模式是动态添加、删除功能。


比如,一个对象需要具备 10 种功能,但客户端可能要求分阶段使用对象功能:在第一阶段只执行第 1-8 项功能, 第二阶段执行第 3-10 项功能,这种场景下只需先定义好第 3-8 项功能方法。在程序运行的第一个阶段,使用具体 装饰者 A 添加 1、2 功能;在第二个运行阶段,使用具体装饰者 B 添加 9、10 功能。而继承关系难以实现这种需 求,它必须在编译期就定义好要使用的功能。  


VS 代理模式


装饰者模式常常被拿来和代理模式比较,两者都要实现目标类的相同接口、声明一个目标对象,并且都可以在不修 改目标类的前提下进行方法扩展,整体设计思路非常相似。那么两者的区别是什么呢?


首先,装饰者模式的重点在于增强目标对象功能,而代理模式的重点在于保护和隐藏目标对象。其中,装饰者模式 需要客户端明确知道目标类,才能对其功能进行增强;代理模式要求客户端对目标类进行透明访问,借助代理类来 完成相关控制功能(如日志记录、缓存设置等),隐藏目标类的具体信息。可见,代理类与目标类的关系往往在编 译时就确定下来,而装饰者类在运行时动态构造而成。


其次,两者获取目标类的方式不同。装饰者模式是将目标对象作为参数传给构造方法,而代理模式是通过在代理类 中创建目标对象的一个实例。


最后,通过上述示例可发现,装饰者模式会使用一系列具体装饰者类来增强目标对象的功能,产生了一种连续、叠 加的效应;而代理模式是在代理类中一次性为目标对象添加功能。  


VS 适配器模式


两者都属于包装式行为,即当一个类不能满足需求时,创建辅助类进行包装以满足变化的需求。但是装饰者模式的 装饰者类和被装饰类都要实现相同接口,或者装饰类是被装饰类的子类;而适配器模式中,适配器和被适配的类可 以有不同接口,并且可能会有部分接口重合。


带你读《2022技术人的百宝黑皮书》——浅析设计模式3 —— 装饰者模式(3)

https://developer.aliyun.com/article/1262380?groupCode=taobaotech

相关文章
|
12天前
|
设计模式 前端开发 JavaScript
【JavaScript 技术专栏】JavaScript 设计模式与实战应用
【4月更文挑战第30天】本文探讨JavaScript设计模式在提升开发效率和代码质量中的关键作用。涵盖单例、工厂、观察者、装饰器和策略模式,并通过实例阐述其在全局状态管理、复杂对象创建、实时数据更新、功能扩展和算法切换的应用。理解并运用这些模式能帮助开发者应对复杂项目,提升前端开发能力。
|
4月前
|
设计模式 数据库连接 数据库
发挥设计模式单例模式的力量:从技术到社会的转变
发挥设计模式单例模式的力量:从技术到社会的转变
|
2月前
|
设计模式 安全 Java
【分布式技术专题】「Tomcat技术专题」 探索Tomcat技术架构设计模式的奥秘(Server和Service组件原理分析)
【分布式技术专题】「Tomcat技术专题」 探索Tomcat技术架构设计模式的奥秘(Server和Service组件原理分析)
35 0
|
5月前
|
设计模式 Java
Java设计模式【十】:装饰者模式
Java设计模式【十】:装饰者模式
23 0
|
1天前
|
设计模式
LabVIEW状态机设计模式技术手册和练习
LabVIEW状态机设计模式技术手册和练习
|
18天前
|
设计模式 存储 前端开发
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
|
21天前
|
设计模式 Java
【设计模式系列笔记】装饰者模式
装饰者模式是一种结构型设计模式,它允许你通过将对象放入包含行为的特殊封装类中来为原始对象添加新的行为。这种模式可以动态地将责任附加到对象上,而不影响其它对象。
38 11
|
3月前
|
设计模式 缓存 安全
设计模式-代理模式(静态代理、动态代理、cglib代理)、代理模式和装饰者模式的区别
设计模式-代理模式(静态代理、动态代理、cglib代理)、代理模式和装饰者模式的区别
|
4月前
|
设计模式 Go 开发工具
Golang设计模式——22装饰者模式
Golang设计模式——22装饰者模式
25 0
|
5月前
|
Java 应用服务中间件 数据库连接
太厉害!Redis+Nginx+设计模式+Spring全家桶+Dubbo技术精选合集
最近花了很长的时间去搜罗Java核心技术好文,我把每个Java核心技术的优选文章都整理成了一个又一个的文档。昨天也是终于全部整理好了,今天就把这些东西分享给老铁们,也能为老铁们省去不少麻烦,想学什么技能了,遇到哪方面的问题了 直接打开文档学一学就好了。不多bb了,直接上干货!