一、装饰者模式(Decorator)
1、装饰者模式定义
(1)装饰者模式:动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(OCP);
(2)这里提到的动态的将新功能附加到对象 和 OCP 原则,下面使用代码的方式学习。
2、装饰者模式原理
(1)装饰者模式就像打包一个快递;
-
-
-
- 主体:比如:陶瓷,衣服 //被修饰者;
- 包装:比如:报纸填充、塑料泡沫、纸板、木板 //装饰者 Decorator
-
-
(2)Component 主体:比如类似前面的 Drink
(3)ConcreteComponent 和 Decorator
① ConcreteComponent:具体的主体;比如前面的各个单品咖啡;
② Decorator:装饰者,比如各种调料;
(4)在如图的 Component 与 ConcreteComponent 之间,如果 ConcreteComponent 类很多,还可以设计一个缓冲层,将共有的部分提取出来,抽象层一个类。
二、装饰者模式解决星巴克咖啡订单分析
说明:
1、Drink 类就是前面说的抽象类,Component;
2、ShortBlack 就是单品咖啡;
3、Decorator 是一个装饰类,喊有一个被装饰的对象(Drink obj);
4、Decorator 的 cost 方法进行一个费用的叠加计算,递归的计算价格;
三、用装饰者模式解决咖啡订单需求
1、装饰者模式下的订单:2分巧克力 + 1份牛奶的 LongBlack
说明:
(1)Milk 包含了 LongBlack;
(2)一份 Chocolate 包含了(Milk + LongBlack)
(3)一份 Chocolate 包含了 (Chocolate + Milk + LongBlack)
(4)这样不管是什么形式的单品咖啡 + 调料组合,通过递归方式可以方便的组合和维护;
2、装饰者模式咖啡订单项目应用实例
抽象类:Drink
1 public abstract class Drink {
2
3 public String des; //描述
4 private float price = 0.0f;
5
6 public String getDes() {
7 return des;
8 }
9
10 public void setDes(String des) {
11 this.des = des;
12 }
13
14 public float getPrice() {
15 return price;
16 }
17
18 public void setPrice(float price) {
19 this.price = price;
20 }
21
22 /**
23 * 计算费用的抽象方法,子类来实现
24 * @return
25 */
26 public abstract float cost();
27 }
主体类:Coffee 及其下面多种类型的实现
1 public class Coffee extends Drink{
2
3 @Override
4 public float cost() {
5 return super.getPrice();
6 }
7 }
8
9 --------------------------------------
10 public class ShortBlack extends Coffee {
11
12 public ShortBlack() {
13 setDes("ShortBlack");
14 setPrice(4.0f);
15 }
16 }
17
18 --------------------------------------
19 public class LongBlack extends Coffee {
20
21 public LongBlack() {
22 setDes("LongBlack");
23 setPrice(5.0f);
24 }
25 }
26 --------------------------------------
27 public class Espresso extends Coffee {
28
29 public Espresso() {
30 setDes("意大利咖啡");
31 setPrice(6.0f);
32 }
33
34 }
35 --------------------------------------
36 public class DeCaf extends Coffee {
37
38 public DeCaf() {
39 setDes("无因咖啡");
40 setPrice(1.0f);
41 }
42 }
装饰类:Decorator 及其下面多种调料
1 public class Decorator extends Drink {
2
3 private Drink obj;
4
5 /**组合进去**/
6 public Decorator(Drink obj) {
7 this.obj = obj;
8 }
9
10 @Override
11 public float cost() {
12 // getPrice() 自己价格
13 return super.getPrice() + obj.cost();
14 }
15
16 @Override
17 public String getDes() {
18 // obj 被装饰者的信息
19 return super.des + " " + super.getPrice() + "&&" + obj.getDes();
20 }
21 }
22 ----------------------------------------------
23 public class Milk extends Decorator {
24 /**
25 * 组合进去
26 *
27 * @param obj
28 **/
29 public Milk(Drink obj) {
30 super(obj);
31 setDes("牛奶");
32 setPrice(2.0f);
33 }
34 }
35 ----------------------------------------------
36 public class Chocolate extends Decorator {
37 /**
38 * 组合进去
39 *
40 * @param obj
41 **/
42 public Chocolate(Drink obj) {
43 super(obj);
44 setDes("巧克力");
45 setPrice(3.0f);
46 }
47 }
48 ----------------------------------------------
49 public class Soy extends Decorator {
50 /**
51 * 组合进去
52 *
53 * @param obj
54 **/
55 public Soy(Drink obj) {
56 super(obj);
57 setDes("豆浆");
58 setPrice(1.5f);
59 }
60 }
61 ----------------------------------------------
咖啡店测试类:
1 public class CoffeeBar {
2 public static void main(String[] args) {
3 //装饰者模式的订单:2份巧克力 + 一份牛奶的 LongBlack
4
5 //1.点一份 LongBlack
6 Drink order = new LongBlack();
7 System.out.println("单品费用1=" + order.getPrice() + " 描述信息=" + order.getDes());
8
9 //2.加入一份牛奶
10 order = new Milk(order);
11 System.out.println("order 加入牛奶费用2=" + order.getPrice() + " 描述信息=" + order.getDes());
12
13 //3.加入一份巧克力
14 order = new Chocolate(order);
15 System.out.println("order 又加入巧克力费用3=" + order.getPrice() + " 描述信息=" + order.getDes());
16
17 //4.再加入一份巧克力
18 order = new Chocolate(order);
19 System.out.println("order 两份巧克力,一份牛奶费用4=" + order.getPrice() + " 描述信息=" + order.getDes());
20 }
21 }
运行结果:
单品费用1=5.0 描述信息=LongBlack
order 加入牛奶费用2=2.0 描述信息=牛奶 2.0&&LongBlack
order 又加入巧克力费用3=3.0 描述信息=巧克力 3.0&&牛奶 2.0&&LongBlack
order 两份巧克力,一份牛奶费用4=3.0 描述信息=巧克力 3.0&&巧克力 3.0&&牛奶 2.0&&LongBlack