本文共 1604 字,大约阅读时间需要 5 分钟。
装饰者模式是面向对象编程中常用的一种高级设计模式。它允许我们对一对象的行为和属性进行动态的扩展,而无需修改现有的类结构。这与传统的继承方式相比,具有更高的灵活性和可扩展性。在本文中,我们将逐步阐述装饰者模式的设计思想、实现原理及其在实际项目中的应用实例。
星巴克咖啡订单项目中,我们需要处理多种咖啡单品及其调料组合。选择传统的继承方式会导致大量waitlist类的生成,当需要新增单品咖啡或调料时,类的数量会呈指数级增长,导致维护成本高昂。为了解决这一问题,装饰者模式提供了一种更加灵活的解决方案。
基类设计:
Drink
abstract类,代表所有咖啡饮品。Drink类
,如ShortBlack
、Espresso
等。Coffee
concrete类继承自Drink类
,用于具体实现咖啡的价格和描述。装饰者类设计:
Decorator
类,作为基装饰者,持有一个Drink
对象。Milk
、Soy
等继承自Decorator类
,它会在Coffee
或Drink
的基础上增加调料的描述和价格。动态组合:
LongBlack
加上一份Milk
和两份Chocolate
,可以通过多次调用Decorator
构造相应的饮品。装饰者模式的核心思想是动态地对一个对象的行为进行扩展。与传统的继承方式相比,其优点:
以咖啡订单项目为例:
// 点一份长黑咖啡Drink order = new LongBlack();// 加入牛奶order = new Milk(order);// 加入一道巧克力order = new Chocolate(order);// 再加一道巧克力,可以叠加多个装饰者order = new Chocolate(order);// 最终价格:LongBlack的价格 + 牛奶的价格 + 两次巧克力的价格System.out.println("总费用:" + order.cost());
每个Decorator
类通过持有原始饮品对象和在cost()
、getDes()
等方法中递归调用原始对象的方法,动态构建最终的饮品描述和价格。
在Java标准库中,装饰者模式广泛用于文件读取和数据加工流程。例如,FilterInputStream
类就是一个典型的装饰者类,它包裹了原始的InputStream
对象,并对其输入流程进行扩展。例如:
public abstract class InputStream implements Closeable { // 基本输入流操作方法 ...}public class FilterInputStream extends InputStream { protected volatile InputStream in; public FilterInputStream(InputStream input) { this.in = input; } // 具体实现输入流操作,如读取数据时进行过滤 public int read(byte[] b, int off, int len) { return in.read(b, off, len); } ...}
这个设计模式的优点显而易见:无论是向现有的类添加新功能,还是修改现有行为,仅需创建新的装饰者类即可,而无需修改原始类结构。
转载地址:http://tctzk.baihongyu.com/