了解一些使用案例,并写一些例子,对装饰者模式有一个入门。
1. 装饰者模式
装饰者模式是继承关系的一个替代方案,它可以动态地将功能附加到对象上,提供了比继承更有弹性的替代方案。
适用场景:
需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实,这时需要装饰者模式。
装饰者模式的作用:
- 可以动态地给一个对象添加一些额外的职责;
- 可以增加一些基础功能而组合大量的功能(这是继承实现不了的)。
2. 使用案例:
2.1. java的IO流
其中buffer附加了缓冲区的功能、InputStream附加了编码方式,而实际读取文件的还是FileInputStream,前两者只是增强或是丰富了功能。
2.2. spark的RDD算子
实际触发执行的是collect算子。
与javaIO不同的是:RDD可自定义每个算子的处理逻辑:即控制抽象。而java IO如上是直接拿来用的。
控制抽象:将封装的逻辑打包发给它,它便具有了此功能。
3. 实现装饰者
3.1. 需求描述
3.2. 逻辑描述
- drink是咖啡种类抽象类,具体的咖啡种类可以通过继承实现;
- decorator是装饰的逻辑:定义了具体那种咖啡和口味是如何组合的逻辑,并且根据不同的口味继承实现不同的组合逻辑
- 通过以组合的方式可以动态实现:不同口味的各种咖啡
咖啡的抽象与实现
public abstract class Drink {
public String des; //要添加的口味
private float price = 0.0f;
//... set and get: des and price
//计算费用的抽象方法
//子类来实现
public abstract float cost();
}
public class DeCaf extends Drink {
public DeCaf() {
setDes(" 无因咖啡 ");
setPrice(1.0f);
}
}
口味的实现与抽象
//装饰者: 组装口味和Drink的逻辑
//通过继承drink使得装饰者也有drink的属性
public class Decorator extends Drink {
private Drink obj; //继承+组合
public Decorator(Drink obj) { //组合
this.obj = obj;
}
@Override
public float cost() {
// 单品价格(单品实现了父类,通过父类方法获取单品价格)+装饰价格
return super.getPrice() + obj.cost();
}
@Override
public String getDes() {
// obj.getDes() 输出被装饰者的信息
return des + " " + getPrice() + " && " + obj.getDes();
}
}
//具体的Decorator, 这里具体指巧克力口味
public class Chocolate extends Decorator {
public Chocolate(Drink obj) {
super(obj);
setDes(" 巧克力 ");
setPrice(3.0f); // 调味品 的价格
}
}
client调用
Drink order2 = new DeCaf();
System.out.println("order2 无因咖啡 费用 =" + order2.cost());
System.out.println("order2 无因咖啡 描述 = " + order2.getDes());
order2 = new Chocolate(order2);
System.out.println("order2 无因咖啡 加入一份Chocolate 费用 =" + order2.cost());
System.out.println("order2 无因咖啡 加入一份Chocolate 描述 = " + order2.getDes());