介绍装饰者的四大问题
- 现在的写法有什么问题吗?
- 为什么要用装饰者模式?
- 什么是装饰者模式?
- 装饰者模式有什么好处?
采用一个案例来说明问题
- 现在要设计一个买奶茶系统,奶茶可分为绿茶,红茶,可以加入配料椰果,红豆等,设计这样一个系统。
目前设计思路
方式一
- 寻找奶茶的共通之处,创建一个抽象茶类
- cost() :计算金额
- getDescription() : 获取奶茶名称
- description: 奶茶名称属性
- 然后针对不同的搭配创建各自的奶茶类
- 绿茶
- 红茶
- 椰果绿茶
- 椰果红茶
- 红豆绿茶
- 红豆红茶
- 椰果红豆绿茶
- 椰果红豆红茶
方式二
- 寻找奶茶的共通之处,创建一个抽象茶类
- cost() :计算金额
- getDescription() : 获取奶茶名称
- description: 奶茶名称属性
- 椰果布尔值
- 红豆布尔值
- 根据椰果和红豆的布尔值判断是否加了配料,然后根据此计算名称和价格
现在的写法有什么问题吗?
- 方式一
- 随着不断的增加配料和茶的种类,类的数量会成倍的增加
- 方式二
- 每此增加配料需要修改已有的代码,违反了设计原则之类应该对扩展开发,对修改关闭
什么是装饰者模式?
- 装饰者模式可以动态的将责任附加到对象上,想要拓展功能,装饰者提供有别于继承的另一种选择
采用装饰者模式进行代码的重构
- 创建抽象茶类
- 创建绿茶类继承茶类,实现名称和花费方法
- 创建抽象装饰者类,继承抽象茶类
- 创建红豆类,继承抽象装饰者类,并有一个tea的实例对象,以改变名称和价格
- 创建椰果类,继承抽象装饰者类,并有一个tea的实例对象,以改变名称和价格
Tea
public abstract class Tea {
String description;
public String getDescription() {
return description;
}
public abstract double cost();
}
GreenTea
public class GreenTea extends Tea {
public GreenTea() {
this.description = "绿茶";
}
@Override
public String getDescription() {
return super.getDescription();
}
@Override
public double cost() {
return 10;
}
}
IngredientDecorator
public abstract class IngredientDecorator extends Tea {
public abstract String getDescription();
}
RedBean
public class RedBean extends IngredientDecorator {
Tea tea;
public RedBean(Tea tea) {
this.tea = tea;
}
@Override
public String getDescription() {
return tea.getDescription() + ", 红豆";
}
@Override
public double cost() {
return 2 + tea.cost();
}
}
Coconut
public class Coconut extends IngredientDecorator {
Tea tea;
public Coconut(Tea tea) {
this.tea = tea;
}
@Override
public String getDescription() {
return tea.getDescription() + ", 椰果";
}
@Override
public double cost() {
return 3 + tea.cost();
}
}
Main
public class Main {
public static void main(String[] args) {
Tea tea = new GreenTea();
tea = new RedBean(tea);
System.out.println(tea.getDescription() + " $" + tea.cost());
}
}
/// out
绿茶, 红豆 $12.0
装饰者模式有什么好处?
- 每当我们新增种类无需修改原本的类
- 符合类应该对扩展开放,对修改关闭
- 但是也存在一些问题就是类会变多导致搞不清楚关系
END
不慕招式,勤修内功