本文已参与「新人创作礼」活动,一起开启掘金创作之路
首先来看看装饰者模式的概念
动态地将责任附加到对象上,若想要扩展功能,装饰着提供了比继承更具有弹性的替代方案
假设我们要开一家咖啡店,客户可以自行选择加什么配料,我们需要根据配料算出最终的价格
如果我们的咖啡只有美式咖啡和摩卡咖啡两种,配料有牛奶和豆浆两种,那么按照传统的方式,我们需要的类有:美式咖啡、美式牛奶加牛奶、美式咖啡加豆浆、美式咖啡加牛奶加豆浆、摩卡咖啡、摩卡咖啡加牛奶……仅仅这么少的品种都能引出这么多类,在真实的店铺中如果我们这么做,那么将会带来极大的不便,而且一旦我们修改了某个配料或咖啡的价格,那么要修改与其相关的所有类,想想都可怕
于是我们可以利用装饰者模式来将客户想要的配料动态的加到咖啡上,不仅如此,我们还可以让客户动态选择大杯、小杯、或中杯
先建立一个抽象的饮料类
public abstract class Beverage {
String description = "Unknown Beverage";
String size = "Unknown Size";
public String getDescription() {
return description;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
public abstract double cost();
}
建立一个配料类(也就是装饰者)
public abstract class CondimentDecorator extends Beverage{
public abstract String getDescription();
}
接下来创建几种咖啡
//蒸馏咖啡
public class Espresso extends Beverage{
public Espresso() {
description = "Espresso";
}
//蒸馏咖啡价格
@Override
public double cost() {
return 10;
}
}
//星巴克首选咖啡
public class HouseBlend extends Beverage{
public HouseBlend() {
description = "House Blend Coffee";
}
//星巴克首选咖啡价格
@Override
public double cost() {
return 15;
}
}
再创建几种配料
public class Soy extends CondimentDecorator{
//配料要加到哪种咖啡上
Beverage beverage;
public Soy(Beverage beverage) {
this.beverage = beverage;
}
public String getSize() {
return beverage.getSize();
}
@Override
public String getDescription() {
// TODO Auto-generated method stub
return beverage.getDescription() + "," + "soy," + beverage.getSize();
}
//计算加上配料并选择规格后的总体咖啡价格
@Override
public double cost() {
// TODO Auto-generated method stub
double cost = beverage.cost();
if(getSize().equals("small")) {
cost += 3;
}else if(getSize().equals("middle")) {
cost += 5;
}else if(getSize().equals("big")){
cost += 6;
}
return cost;
}
}
public class Mocha extends CondimentDecorator{
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ",Mocha";
}
@Override
public double cost() {
return 5 + beverage.cost();
}
}
最后我们来测试一下代码
public class StarbuzzCoffee {
public static void main(String[] args) {
//点一杯蒸馏咖啡
Beverage beverage = new Espresso();
//选择大杯
beverage.setSize("big");
//加豆浆
beverage = new Soy(beverage);
//加摩卡
beverage = new Mocha(beverage);
System.out.println(beverage.getDescription() + "$" + beverage.cost());
Beverage beverage2 = new HouseBlend();
beverage2.setSize("big");
beverage2 = new Soy(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Mocha(beverage2);
System.out.println(beverage2.getDescription() + "$" + beverage2.cost());
}
}
这样就能正确帮我们计算出最终的结果了