首页 > 装饰模式(Decorator)

装饰模式(Decorator)

1、概念

装饰模式动态地给一个对象添加一些额外的职责。就扩展功能而言,它比生成子类方式更为灵活,属于结构性模式一种。

2、模式结构

  • 抽象组件角色(Component):定义一个对象接口,以规范准备接受附加责任的对象,即可以给这些对象动态地添加职责。
  • 具体组件角色(ConcreteComponent) :被装饰者,定义一个将要被装饰增加功能的类。可以给这个类的对象添加一些职责。
  • 抽象装饰器(Decorator):维持一个指向构件Component对象的实例,并定义一个与抽象组件角色Component接口一致的接口。
  • 具体装饰器角色(ConcreteDecorator):向组件添加职责。

3、使用场景

  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
  • 需要动态地给一个对象增加功能,这些功能也可以动态地被撤销
  • 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。不能采用继承的情况主要有两类:第一类是系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长;第二类是因为类定义不能继承(如final类)

4、优缺点

优点:

  • 装饰模式可以提供比继承更多的灵活性
  • 通过配置文件可以在运行时选择不同的装饰器,从而实现不同的行为
  • 使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合
  • 具体构件类与具体装饰类可以独立变化,原有代码无须改变,符合“开闭原则”

缺点:

  • 装饰类和小对象的产生将增加系统的复杂度,加大学习与理解的难度
  • 多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐

5、实例

在购买奶茶的时候,经常会有选择配料的选项,每种配料的价格不一样,可以多种组合,价格也不一样。首先先定义奶茶的接口,具有名称和价格方法

public interface IMilkTea {String name();double price();
}

继承IMilkTea的相关茶类

public class RedTea implements IMilkTea {@Overridepublic String name() {return "红茶";}@Overridepublic double price() {return 10;}
}
public class GreenTea implements IMilkTea {@Overridepublic String name() {return "绿茶";}@Overridepublic double price() {return 12;}
}

定义具体装饰类Decorator,装饰相关奶茶

public class Decorator implements IMilkTea {@Overridepublic String name() {return null;}@Overridepublic double price() {return 0;}
}

继承Decorator的相关类

public class IceCream extends Decorator {private String name = "加雪糕";private IMilkTea milkTea;public IceCream(IMilkTea milkTea) {this.milkTea = milkTea;}@Overridepublic String name() {return milkTea.name() + name;}@Overridepublic double price() {return milkTea.price() + 3;}
}
public class Pearl extends Decorator {private String name = "加珍珠";private IMilkTea milkTea;public Pearl(IMilkTea milkTea) {this.milkTea = milkTea;}@Overridepublic String name() {return milkTea.name() + name;}@Overridepublic double price() {return milkTea.price() + 2;}
}

客户端使用

public static void main(String[] args) {IMilkTea milkTea = new RedTea();milkTea = new IceCream(milkTea);milkTea = new Pearl(milkTea);System.out.println(milkTea.name() + "
价格:" + milkTea.price());
}

转载于:https://www.cnblogs.com/fomin/p/9933956.html

更多相关:

  • 点云PCL免费知识星球,点云论文速读。文章:DSP-SLAM: Object Oriented SLAM with Deep Shape Priors作者:Jingwen Wang Martin Runz Lourdes Agapito编译:点云PCL代码:https://github.com/JingwenWang95/DSP-S...

  • RAM缓存 新RAM缓存算法(CLFUS) 新的RAM缓存使用的创意来自许多缓存替换策略和算法,包括LRU,LFU,CLOCK,GDFS及2Q,它被命名为时钟周期内最小频繁使用大小算法CLFUS(Clocked Least Frequently Used by Size)。它避开了任何专利算法,具有如下特性: 均衡最近性(Rec...

  • MP4 |视频:AVC,1280×720 30 fps |音频:AAC,48 KHz,2 Ch |时长:2h 12m 语言:英语+中英文字幕(根据原英文字幕机译更准确)|大小解压后:560M C4D是一个有抱负的运动图形艺术家和设计师的重要工具。借助C4D,您可以使用3D对象、动态效果和动画来增强运动图形、模型和可视化效果。本课...

  • 文章目录先说问题:再说解决尝试1:尝试2(该尝试建议先在自己环境搭配对应业务测试通过后再现场尝试): 感谢 学无止境996同学的陪伴和vigourtyy美丽女友的支持,直到这个解决问题的深夜 先说问题: ceph 12.2.1生产环境:3副本 tier + 3副本data 机房在拥有业务的情况下重启集群交换机,产生如下场景...

  • 这周主要学习了java中的类和对象的知识点,发现和C++中的类和对象极为相似,对于类和对象的概念理解起来也简单。同时在自学的过程中也把类的知识重新复习巩固了一下(如类的三大特征:继承,封装和多态,构造,成员对象的访问权限,构造,无参有参函数的调用等),同时也了解到一些新的概念,比如类对象创建和引用占据堆内存和栈内存,输出对象时默认调...