定义:动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更加弹性的解决方案。
1 引例_咖啡订单系统
1.1 最初设计。
如图1,首先创建一个Bevarage(饮料)的抽象类,店内所有的咖啡都继承这个类。description是成员变量,由子类设置,描述咖啡使用。getDescription()
就是返回这个描述。cost()
方法是抽象方法,由子类实现,计算价格使用。
最开始咖啡就有如下4个(对咖啡不太了解,中文名字错了不要在意):DarkRoast(超优深焙咖啡),Espresso(浓缩咖啡),Decaf(低卡咖啡),HouseBlend(混合咖啡)
但客人要求在咖啡里添加调料:Milk(奶),Soy(豆浆),Mocha(摩卡),每种调料都有单独的价钱,所以设计上又添加了这些,如图2。
这里我们可以看出问题,图2中只是列出了三种组合,我们可以想一下,这种组合是由很多种的,现在是4款咖啡,3种调料,在考虑到以后,可定会推出更多的咖啡和各种调料。这样维护起来,类会爆炸的,而且有的人还喜欢double份的Mocha,这样算的话类就会无穷无尽,而且物价是波动的,你还会修改价格,这样维护起来会死人的。
1.2 进一步改进
如图3,这次将调料加入Bevarage
中的成员变量中,并加入相应的has和set方法,cost()
方法现在提供实现,计算出调料的价格。再由子类加上咖啡的价格计算出最后的售价。
尽管这样,我们还可以看出问题:
(1)调料种类,价格变动,都会影响基类的cost()
方法。
(2)基类很多方法对某一种咖啡可能带来不适应。
(3)顾客要了double份的Milk如何解决。
这就违背下面的设计原则。
设计原则:类应该对扩展开放,对修改关闭。
3.2 认识装饰者模式
1.如图4:以DarkRoast为例。顾客点了一杯DarkRoast,DarkRoast继承Beverage
类,可以调用cost()
方法计算价格。
2.如图5:顾客加了一份摩卡调料,这时建立一个Mocha的对象,包裹住DarkRoast。这里Mocha是装饰者,它的类型反应了装饰对象的类型,反应换句换说就是和装饰的对象的类型相一致。
3.如图6 ,顾客又加了一份奶泡调料,这时在创建一个Whip装饰者,装饰刚刚加了摩卡的DarkRoast的咖啡。
4.如图7 结账。调用最外层的cost()
方法即可。
3.3 咖啡订单系统
3.3.1 类图
1.Bevarage
是抽象类,其中cost()
方法是抽象方法。
2.四种咖啡都继承Bevarage
。
3.新建一个调料抽象类CondimentDecorator
,四种调料均继承此抽象类。
3.3.2 代码实现
1.Bevarage
和四种咖啡。
public abstract class Beverage {
String description = "原味 咖啡";
public String getDescription() {
return description;
}
public abstract double cost();
}
public class DarkRoast extends Beverage {
public DarkRoast() {
description = "DarkRoast";
}
@Override
public double cost() {
return 1.52;
}
}
public class Espresso extends Beverage {
public Espresso() {
description = "Espresso";
}
public double cost() {
return 1.99;
}
}
public class Decaf extends Beverage {
public Decaf() {
description = "Decaf";
}
@Override
public double cost() {
return 0.76;
}
}
public class HouseBlend extends Beverage {
public HouseBlend() {
description = "HouseBlend";
}
@Override
public double cost() {
return 0.89;
}
}
2.抽象类CondimentDecorator
和3种调料。
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
public class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage){
this.beverage=beverage;
}
public String getDescription() {
return beverage.getDescription()+", Mocha";
}
public double cost() {
return 0.20+beverage.cost();
}
}
public class Soy extends CondimentDecorator {
Beverage beverage;
public Soy(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Soy";
}
public double cost() {
return beverage.cost() + 1.30;
}
}
public class Whip extends CondimentDecorator {
Beverage beverage;
public Whip(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Whip";
}
public double cost() {
return beverage.cost() + 0.54;
}
}
3.测试代码。
public class StarbuzzCoffee {
public static void main(String[] args) {
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + " $" + beverage.cost());
Beverage beverage1 = new DarkRoast();
beverage1 = new Mocha(beverage1);
beverage1 = new Mocha(beverage1);
beverage1 = new Whip(beverage1);
System.out.println(beverage1.getDescription() + " $" + beverage1.cost());
Beverage beverage2 = new HouseBlend();
beverage2 = new Soy(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
}
}
来源:CSDN
作者:###keer###
链接:https://blog.csdn.net/weixin_41938180/article/details/104146695