参考:head-first-设计模式
定义
装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案
这个模式主要就是,装饰类和被装饰类需要继承同一个超类,实现超类里面的抽象方法
问题描述
一个咖啡店,需要统计订单上的咖啡,以及加的配料,算总价,配料数量、种类经常变化
项目结构
如下,最下面的Beverage就是饮料的超类
类图
先编写饮料的超类
//饮料的超类
public abstract class Beverage {
//定义描述字段
public String description = "Unknown Description";
//获取价格
public abstract double cost();
//获取描述
public String getDescription(){
return description;
}
//控制台打印描述和价格
public void printDescriptionAndCost(){
System.out.println(this.getDescription() + " $" + this.cost());
}
}
编写咖啡实现类,继承超类
//浓缩咖啡
public class Espresso extends Beverage {
//构造器中赋值描述
public Espresso() {
description = "Espresso Coffee";
}
@Override
public double cost() {
return 1.99;
}
}
//综合咖啡
public class HouseBlend extends Beverage {
//构造器中赋值描述
public HouseBlend() {
description = "House Blend Coffee";
}
@Override
public double cost() {
return 0.89;
}
}
编写配料装饰抽象类继承超类
//调料的抽象类
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
编写配料实现类,继承配料装饰抽象类
//牛奶
public class Milk extends CondimentDecorator {
//声明超类
Beverage beverage;
//构造器中赋值超类
public Milk(Beverage beverage) {
this.beverage = beverage;
}
@Override
public double cost() {
return 0.1 + beverage.cost();
}
@Override
public String getDescription() {
return beverage.getDescription() + ",Milk";
}
}
//摩卡
public class Moka extends CondimentDecorator {
//声明超类
Beverage beverage;
//构造器中赋值超类
public Moka(Beverage beverage) {
this.beverage = beverage;
}
@Override
public double cost() {
return 0.2 + beverage.cost();
}
@Override
public String getDescription() {
return beverage.getDescription() + ",Moka";
}
}
//豆浆
public class Soy extends CondimentDecorator {
//声明超类
Beverage beverage;
//构造器中赋值超类
public Soy(Beverage beverage) {
this.beverage = beverage;
}
@Override
public double cost() {
return 0.15 + beverage.cost();
}
@Override
public String getDescription() {
return beverage.getDescription() + ",Soy";
}
}
//奶泡
public class Whip extends CondimentDecorator {
//声明超类
Beverage beverage;
//构造器中赋值超类
public Whip(Beverage beverage) {
this.beverage = beverage;
}
@Override
public double cost() {
return 0.1 + beverage.cost();
}
@Override
public String getDescription() {
return beverage.getDescription() + ",Whip";
}
}
测试类,测试
@Test
public void testDecorator() {
//一杯加牛奶、豆浆、奶泡的浓缩咖啡
Beverage beverage = new Espresso();
//加牛奶
beverage = new Milk(beverage);
//加豆浆
beverage = new Soy(beverage);
//加奶泡
beverage = new Whip(beverage);
//输出
beverage.printDescriptionAndCost();
//一杯啥都不加的综合咖啡
Beverage beverage1 = new HouseBlend();
beverage1.printDescriptionAndCost();
}
控制台打印
如果现在需要在菜单上新增加一个杯子容量的描述,小杯,中杯和大杯,中杯要贵1美元,大杯要贵两美元,下面我们改一下代码
先修改超类
//饮料的超类
public abstract class Beverage {
// 定义描述字段
public String description = "Unknown Description";
//容量,默认小杯
public String size = GRANDE;
//容量定义
public static String TALL = "大";
public static String GRANDE = "中";
public static String VENTI = "小";
// 获取价格
public abstract double cost();
//获取容量
public String getSize() {
return size;
}
// 获取描述
public String getDescription() {
return description;
}
// 控制台打印描述和价格
public void printDescriptionAndCost() {
System.out.println(this.getDescription() + " $" + this.cost());
}
}
然后修改咖啡类型的类
//浓缩咖啡
public class Espresso extends Beverage {
//构造器中赋值描述
public Espresso() {
description = "Espresso Coffee, " + VENTI;
}
//构造器中赋值描述
public Espresso(String size) {
this.size = size;
description = "Espresso Coffee, " + size;
}
@Override
public double cost() {
Double cost = 1.99;
if (getSize() == TALL) {
cost += 2.00;
} else if (getSize() == GRANDE){
cost += 1.00;
}
return cost;
}
}
//综合咖啡
public class HouseBlend extends Beverage {
//构造器中赋值描述
public HouseBlend() {
description = "House Blend Coffee, " + VENTI;
}
//构造器中赋值描述
public HouseBlend(String size) {
this.size = size;
description = "House Blend Coffee, " + size;
}
@Override
public double cost() {
Double cost = 0.89;
if (getSize() == TALL) {
cost += 2.00;
} else if (getSize() == GRANDE){
cost += 1.00;
}
return cost;
}
}
测试一下
@Test
public void testDecorator() {
//一杯加牛奶、豆浆、奶泡的浓缩咖啡
Beverage beverage = new Espresso(Beverage.TALL);
//加牛奶
beverage = new Milk(beverage);
//加豆浆
beverage = new Soy(beverage);
//加奶泡
beverage = new Whip(beverage);
//输出
beverage.printDescriptionAndCost();
//一杯啥都不加的综合咖啡
Beverage beverage1 = new HouseBlend(Beverage.GRANDE);
beverage1.printDescriptionAndCost();
}
打印
这只是一个demo,所以就使用double类型了,涉及到金钱的计算最好还是使用BigDecimal来操作