装饰者模式

装饰者模式

星巴克咖啡订单项目:

1)咖啡种类/单品咖啡:Espresso(意大利浓咖啡)ShortBlack(浓缩咖啡)LongBlack(美式咖啡)Decaf(无因咖啡)

2)调料:MilkSoy(豆浆)、Chocolate

3)要求在扩展新的咖啡种类的时候,具有良好的扩展性、改动方便、维护方便。

4)使用OO(面向对象)的方法来计算不同种类咖啡的费用:客户可以点单品咖啡,也可以点单品咖啡+调料组合。

方案一 较差的传统方案

 

 

这种解决方案会造成类爆炸

方案二 对方案一进行改进

 

 

前面分析到方案一因为咖啡单品+调料组合会造成类爆炸,因此可以做改进,将调料内置到Drink类中,这样就不会造成类的数量过多。从而提高了代码的可维护性。

说明:milk,soy.chocolate可以设计为boolean类型,表示是否需要添加相应的调料。

方案二问题分析:

  1. 方案二可以控制类的数量,不至于造成类的数量过多。
  2. 在增加或者删除调料类的时候,代码的维护量很大(因为都要在同一个Drink类中进行修改)
  3. 考虑到用户可以添加多份调料的时候,可以将hasMilk 返回一个对应的int 类型
  4. 所以我们考虑使用装饰者模式

装饰者模式定义

 

 

 

 

 

 

代码演示:

package com.sky.decorator;

/**
 * 将各种单品咖啡做一个缓存层
 */
public class Coffee extends Drink {

    @Override
    public float cost() {
        return super.getPrice();
    }
}

package com.sky.decorator;

/**
 * 意大利咖啡 要继承缓存层
 */
public class Espresso extends Coffee {

    // 通过构造器,初始化意大利咖啡 描述 和 价格
    public Espresso(){

        setDes(" 意大利咖啡 ");
        setPrice(6.0f);
    }


}

package com.sky.decorator;

/**
 * 美式咖啡
 */
public class LongBlack extends Coffee {

    public LongBlack(){

        setDes(" 美式咖啡 ");
        setPrice(5.0f);
    }
}

package com.sky.decorator;

/**
 * 浓缩咖啡 单品咖啡
 */
public class ShortBlack extends Coffee {

    public ShortBlack(){

        setDes(" 浓缩咖啡 ");
        setPrice(4.0f);
    }
}

package com.sky.decorator;

/**
 * 无因咖啡
 */
public class Decaf extends Coffee {

    public Decaf(){

        setDes(" 无因咖啡 ");
        setPrice(3.0f);
    }
}

	package com.sky.decorator;

/**
 * 抽象类
 */
public abstract class Drink {

    private String des; // 描述
    private float price = 0.0f; // 价格

    // 添加set get 方法
    public String getDes() {
        return des;
    }

    public void setDes(String des) {
        this.des = des;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    // 计算费用的抽象方法 由子类来进行实现
    public abstract float cost();
}

package com.sky.decorator;

/**
 * 装饰者
 */
public class Decorator extends Drink {

    private Drink obj; // 被装饰者

    public Decorator(Drink obj){ // 体现的是一种组合关系

        this.obj = obj;
    }

    @Override
    public float cost() {
        // super.getPrice() 表示自己的价格,其中super.是可以不写的
        return super.getPrice() + obj.cost();
    }

    @Override
    public String getDes() {
        // 其中super.是可以不写的
        // obj.getDes() 表示输出被装饰者的信息
        return super.getDes() + " " + super.getPrice() + " " +  obj.getDes() + " " +  obj.getPrice();
    }
}

package com.sky.decorator;

/**
 * 调味品 巧克力
 */
public class Chocolate extends Decorator {
    public Chocolate(Drink obj) {
        super(obj);
        setDes(" 巧克力 ");
        setPrice(3.0f);
    }
}

package com.sky.decorator;

/**
 * 调味品 牛奶
 */
public class Milk extends Decorator {
    public Milk(Drink obj) {
        super(obj);
        setDes(" 牛奶 ");
        setPrice(2.0f);
    }
}

package com.sky.decorator;

/**
 * 调味品 豆浆
 */
public class Soy extends Decorator {

    public Soy(Drink obj) {
        super(obj);
        setDes(" 豆浆 ");
        setPrice(1.5f);

    }
}

package com.sky.decorator;

public class CoffeeBar {

    public static void main(String[] args) {

        // 使用装饰者模式点一份美式咖啡和两份牛奶

        // 1.先点一份美式咖啡
        Drink order = new LongBlack();
        System.out.println(" 描述:" + order.getDes());
        System.out.println(" 费用:" + order.cost());


        // 2.再加一份牛奶
        order = new Milk(order);
        System.out.println(" 描述:" + order.getDes());
        System.out.println(" 费用:" + order.cost());

        // 3.再加入一份巧克力
        order = new Chocolate(order);
        System.out.println(" 描述:" + order.getDes());
        System.out.println(" 费用:" + order.cost());

        // 3.再加入一份巧克力
        order = new Chocolate(order);
        System.out.println(" 描述:" + order.getDes());
        System.out.println(" 费用:" + order.cost());

        System.out.println("===================================");
        System.out.println("===================================");

        Drink order2 = new Decaf();
        System.out.println(" 描述:" + order2.getDes());
        System.out.println(" 费用:" + order2.cost());

        order2 = new Milk(order2);
        System.out.println(" 描述:" + order2.getDes());
        System.out.println(" 费用:" + order2.cost());


    }
}

 描述: 美式咖啡 
 费用:5.0
 描述: 牛奶  2.0  美式咖啡  5.0
 费用:7.0
 描述: 巧克力  3.0  牛奶  2.0  美式咖啡  5.0 2.0
 费用:10.0
 描述: 巧克力  3.0  巧克力  3.0  牛奶  2.0  美式咖啡  5.0 2.0 3.0
 费用:13.0
===================================
===================================
 描述: 无因咖啡 
 费用:3.0
 描述: 牛奶  2.0  无因咖啡  3.0
 费用:5.0

  

 

posted on 2022-12-03 11:02  ~码铃薯~  阅读(17)  评论(0编辑  收藏  举报

导航