java模式—装饰者模式
在公司上班,经过大半天的忙碌,每到下午三四点,肚子就感觉咕咕叫,嘴巴也挺寂寞的,于是乎就想着点杯奶茶慰劳下自己。喝过奶茶的小伙伴都知道,点奶茶加点配料更爽口,例如燕麦(oats),珍珠(pearl),布丁(pudding)等等,当然了,每种配料的价格都是不一样的,那么我们今天要做的就是,不管你是点奶茶,还是咖啡,还是鲜果茶;不管你在茶里面加布丁、还是珍珠,最终需要展示价格是奶茶基础价加上每一种所选配料价格的总和。例如:奶茶加燕麦,加珍珠,加布丁,销售价格:12.0
规格表如下:
1、下面我们先看代码,再总结:
/** * Created by sww_6 on 2019/4/25. * 被装饰对象的基类 */ public abstract class Tea { public abstract String desc(); public abstract double price(); }
/** * Created by sww_6 on 2019/4/25. * 具体被装饰对象,奶茶基类。 */ public class MilkTea extends Tea { public String desc() { return "奶茶"; } public double price() { return 8; } }
/** * Created by sww_6 on 2019/4/25. * 具体被装饰对象,咖啡基类。 */ public class Coffee extends Tea { public String desc() { return "拿铁"; } public double price() { return 10; } }
/** * Created by sww_6 on 2019/4/25. * 配料装饰者 */ public class DosingDecorator extends Tea { private Tea tea; public DosingDecorator(Tea tea) { this.tea = tea; } public String desc() { return tea.desc(); } public double price() { return tea.price(); } }
/** * Created by sww_6 on 2019/4/25. * 配料具体装饰者,燕麦。 */ public class Oats extends DosingDecorator { public Oats(Tea tea) { super(tea); } @Override public String desc() { return super.desc() + "加燕麦,"; } @Override public double price() { return super.price() + 1; } }
/** * Created by sww_6 on 2019/4/25. * 配料具体装饰者,珍珠。 */ public class Pearl extends DosingDecorator { public Pearl(Tea tea) { super(tea); } @Override public String desc() { return super.desc() + "加珍珠,"; } @Override public double price() { return super.price() + 1; } }
/** * Created by sww_6 on 2019/4/25. * 配料具体装饰者,布丁。 */ public class Pudding extends DosingDecorator { public Pudding(Tea tea) { super(tea); } @Override public String desc() { return super.desc() + "加布丁,"; } @Override public double price() { return super.price() + 2; } }
下面就是测试类。
/** * Created by sww_6 on 2019/4/25. * 测试类,测试奶茶和咖啡。 */ public class Test { public static void main(String[] args) { Tea tea; tea = new Coffee(); System.out.println(tea.desc()+"销售价格:"+tea.price()); tea = new MilkTea(); tea = new Oats(tea); tea = new Pearl(tea); tea = new Pudding(tea); System.out.println(tea.desc() + "销售价格:"+tea.price()); } }
测试结果如下:
拿铁销售价格:10.0
奶茶加燕麦,加珍珠,加布丁,销售价格:12.0
2、类图
大家看,这个类图是不是一目了然呢?
3、参与者
1.Component(被装饰对象的基类),即tea抽象类。
定义一个对象接口,可以给这些对象动态地添加职责。
2.ConcreteComponent(具体被装饰对象),即Coffee和MilkTea类。
定义一个对象,可以给这个对象添加一些职责。
3.Decorator(装饰者抽象类),即DosingDecorator(配料装饰者)类。
维持一个指向Component实例的引用,并定义一个与Component接口一致的接口。
4.ConcreteDecorator(具体装饰者),即珍珠(Pearl),燕麦(Oats),布丁(Pudding)类。
具体的装饰对象,给内部持有的具体被装饰对象,增加具体的职责。
4、涉及角色
(1)抽象组件:定义一个抽象接口,来规范准备附加功能的类
(2)具体组件:将要被附加功能的类,实现抽象构件角色接口
(3)抽象装饰者:持有对具体构件角色的引用并定义与抽象构件角色一致的接口
(4)具体装饰:实现抽象装饰者角色,负责对具体构件添加额外功能。
5、意图:
动态地给一个对象添加一些额外的职责。就增加功能来说, Decorator模式相比生成子类更为灵活。该模式以对客 户端透明的方式扩展对象的功能。