前言
装饰器模式在现实生活中的例子简直太多了。
比如有个手机(裸机Phone类),如果需要不断的为这个Phone增添某个功能从而变成一个新功能的Phone,就需要一个装饰器的类,来动态的给一个类额外添加一个指定的功能,而生成另一个类,但原先的类又没有改变,不影响原有系统的稳定。
比如我开了一个奶茶店,卖的是普通的奶茶。现在我想引入一个叫珍珠奶茶的商品,我要怎么做呢? 我是不是需要升级—下我的制作奶茶的机器,让它支持珍珠奶茶的做法?但这种成本估计比较高,说不定还没原来做奶茶的机器好用呢!实际上我只需要买一个能做“珍珠”的机器就行!把“珍珠”放进奶茶不就成了珍珠奶茶。原有的做奶茶的机器依然可以稳定地制作做奶茶,也避免花成本去学习操作新的机器。在这个案例中,珍珠就是装饰者,奶茶就是被装饰者。
一、装饰器模式简介
装饰器模式指在不改变原有对象结构的基础情况下,动态地给该对象增加一些额外功能的职责。装饰器模式相比生成子类更加灵活。它属于对象结构型模式。
当前有一个功能完善的对象,如果我们想要给这个对象添加一个新的职责,那么我们可以用一个新的类去装饰它来实现对原有对象职责的扩展。新的类称为“装饰者”,原有的对象称为“被装饰者”。这种模式被称为装饰器模式。
二、代码实现
场景:将普通奶茶装饰为珍珠奶茶。
1.定义制作奶茶接口
public interface MilkTeaService {
String generateMilkTea();
}
2.定义普通奶茶类
public class CommonMilkTeaService implements MilkTeaService {
@Override
public String generateMilkTea() {
return "制作奶茶";
}
}
3.定义装饰器类
public class MilkTeaDecorator implements MilkTeaService {
private final MilkTeaService milkTeaService;
public MilkTeaDecorator(MilkTeaService milkTeaService) {
this.milkTeaService = milkTeaService;
}
@Override
public String generateMilkTea() {
String generateMilkTea = milkTeaService.generateMilkTea();
return generateMilkTea + "为珍珠奶茶完成";
}
}
4.测试
@Test
public void test() {
CommonMilkTeaService commonMilkTeaService = new CommonMilkTeaService();
String milkTea = commonMilkTeaService.generateMilkTea();
System.out.println("milkTea = " + milkTea);
MilkTeaDecorator milkTeaDecorator = new MilkTeaDecorator(new CommonMilkTeaService());
String generateMilkTea = milkTeaDecorator.generateMilkTea();
System.out.println("generateMilkTea = " + generateMilkTea);
}
输出:
总结
当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。
使用装饰器模式可以透明且动态地扩展类的功能。
可以对一个对象进行多次装饰。
具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,原有类库代码无须改变,符合“开闭原则”。