简述
装饰者模式的定义为:动态的给一个对象添加其它功能。
从扩展性来说,这种方式比继承更有弹性,更加灵活,装饰者模式也体现了开闭原则(OCP)。
问题背景
星巴克咖啡订单项目(咖啡馆) :
1)咖啡种类/单品咖啡: Espresso(意大利浓咖啡)、ShortBlack、Decaf(无因咖啡)、LongBlack(美式咖啡)
2)配料: Milk、Soy(豆浆)、Chocolate
3)要求在扩展新的咖啡种类时,具有良好的扩展性、改动方便、维护方便
4)使用OO的来计算不同种类咖啡的费用: 客户可以点单品咖啡,也可以单品咖啡+调料组合。
解决方案1:传统方案
1)Drink是一个抽象类,表示饮品。
2)desc是对这个饮品的描述, 比如单品咖啡的名字,单品咖啡+配料
3)cost()方法是这个饮品的费用
最普通的设计就是有多少种组合那就写多少种类,这样排列组合下来类的数量会成倍增加,就会出啊先类爆炸。
解决方案2:解决类爆炸
1)通过往单品咖啡类中增加配料来减少类爆炸。
2)在增加或者删除配料种类时,代码的维护量很大,要维护每一个单品咖啡的类。
3)考虑使用装饰者模式
解决方案3:装饰者模式
装饰者模式原理
这个就是装饰者模式的UML类图,我们来解释一下:
1)Component是一个所有类的超类,都要继承它。
2)ConcreteComponent是被装饰者类
3)Decorator是所有装饰者的超类,装饰者类都要继承Decorator
4)装饰者和被装饰者有着共同的超类型,这一点很重要,因为装饰者必须能够取代被装饰者。这样,装饰者才能在被装饰者的基础上,加上自己的行为,以增强被装饰者的能力。
5)一个被装饰者可以被多个装饰者依次包装,这个包装行为是动态的,不限次数的。
装饰者模式解决星巴克咖啡订单问题
我们来解释一下:
1)Drink就是所有饮品的超类,就是前面所说的Component
2)Coffee是我们单品咖啡的父类
3)Decorator就是配料类的超类,配料就是装饰者。
4)如果我们点了单品咖啡,然后有加了配料,那么我们可以将这个单品咖啡类放到装饰类的Drink属性上,因为都继承了Drink,所以被装饰了的类也是Drink对象,所以如果我们再加配料,仍然可以将这个对象放到新的装饰者(配料)对象中的Drink属性上。
代码示例:
Drink类
public abstract class Drink {
private String desc;
private Double price = 0.00;
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
public abstract Double cost();
}
配料超类(装饰者类)
public class Decorator extends Drink{
private Drink obj;
public Decorator(Drink obj) {
this.obj = obj;
}
@Override
public Double cost() {
return super.getPrice() + obj.cost();
}
@Override
public String getDesc() {
return super.getDesc() + " " + super.getPrice() + " " + obj.getDesc();
}
}
Coffee类
public class Coffee extends Drink{
@Override
public Double cost() {
// 对于单体咖啡就是价格
return super.getPrice();
}
}
单体咖啡类
public class Espresso extends Coffee{
public Espresso() {
setDesc("Espresso");
setPrice(3.00);
}
}
public class LongBlack extends Coffee{
public LongBlack() {
setDesc("ShortBlack");
setPrice(5.00);
}
}
public class ShortBlack extends Coffee{
public ShortBlack() {
setDesc("ShortBlack");
setPrice(4.00);
}
}
配料类
public class Chocolate extends Decorator{
public Chocolate(Drink obj) {
super(obj);
setDesc("Chocolate");
setPrice(1.00);
}
}
public class Milk extends Decorator{
public Milk(Drink obj) {
super(obj);
setDesc("Milk");
setPrice(1.10);
}
}
public class Soy extends Decorator{
public Soy(Drink obj) {
super(obj);
setDesc("Soy");
setPrice(1.20);
}
}
咖啡店类文章来源:https://www.toymoban.com/news/detail-461843.html
public class CoffeeBar {
public static void main(String[] args) {
// 装饰者模式下订单:2份Chocolate + 1份Mikl的LongBlack
// 1.点一份LongBlack
Drink order = new LongBlack();
System.out.println("单体咖啡" + order.getDesc() + "的费用:" + order.cost());
// 2.加入一份Mikl
order = new Milk(order);
System.out.println("单体咖啡" + order.getDesc() + "的费用:" + order.cost());
// 3.加入两份巧克力
order = new Chocolate(order);
order = new Chocolate(order);
System.out.println("单体咖啡" + order.getDesc() + "的费用:" + order.cost());
}
}
源码
GitHub地址:design-patterns文章来源地址https://www.toymoban.com/news/detail-461843.html
到了这里,关于设计模式-装饰器模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!