最近大街上流行起来了“快乐柠檬”,我们把快乐柠檬的饮料分为三类:红茶、绿茶、咖啡,在这三大类的基础上,又增加了许多的口味,什么金桔柠檬红茶、金桔柠檬珍珠绿茶、芒果红茶、芒果绿茶、芒果珍珠红茶、烤珍珠红茶、烤珍珠芒果绿茶、椰香胚芽咖啡、焦糖可可咖啡等等,每家店都有很长的菜单,但是仔细看下,其实原料也没几样,但是可以搭配出很多组合,如果顾客需要,很多没出现在菜单中的饮料他们也是可以做的。
在这个例子中,红茶、绿茶、咖啡是最基础的饮料,其他的像金桔柠檬、芒果、珍珠、椰果、焦糖等都属于装饰用的。当然,在开发中,我们确实可以像门店一样,开发这些类:LemonBlackTea、LemonGreenTea、MangoBlackTea、MangoLemonGreenTea……但是,很快我们就发现,这样子干肯定是不行的,这会导致我们需要组合出所有的可能,而且如果客人需要在红茶中加双份柠檬怎么办?三份柠檬怎么办?
首先,定义饮料抽象基类:
1 2 3 4 5 6
| public abstract class Beverage { public abstract String getDescription(); public abstract double cost(); }
|
然后是三个基础饮料实现类,红茶、绿茶和咖啡:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class BlackTea extends Beverage { public String getDescription() { return "红茶"; } public double cost() { return 10; } }
public class GreenTea extends Beverage { public String getDescription() { return "绿茶"; } public double cost() { return 11; } }
...
|
定义调料,也就是装饰者的基类,此类必须继承自 Beverage:
1 2 3 4
| public abstract class Condiment extends Beverage {
}
|
然后我们来定义柠檬、芒果等具体的调料,它们属于装饰者,毫无疑问,这些调料肯定都需要继承调料 Condiment 类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public class Lemon extends Condiment { private Beverage bevarage; public Lemon(Beverage bevarage) { this.bevarage = bevarage; } public String getDescription() { return bevarage.getDescription() + ", 加柠檬"; } public double cost() { return beverage.cost() + 2; } }
public class Mango extends Condiment { private Beverage bevarage; public Mango(Beverage bevarage) { this.bevarage = bevarage; } public String getDescription() { return bevarage.getDescription() + ", 加芒果"; } public double cost() { return beverage.cost() + 3; } }
...
|
看客户端调用:
1 2 3 4 5 6 7 8 9 10 11 12
| public class Main { public static void main(String[] args) { Beverage beverage = new GreenTea(); beverage = new Lemon(beverage); beverage = new Mongo(beverage);
System.out.println(beverage.getDescription() + " 价格:¥" + beverage.cost()); } }
|
如果我们需要 芒果-珍珠-双份柠檬-红茶:
1
| Beverage beverage = new Mongo(new Pearl(new Lemon(new Lemon(new BlackTea()))));
|
参考