设计模式——装饰者模式

本文通过一个星巴克咖啡订单项目的例子,展示了如何使用装饰者模式解决类爆炸问题并实现灵活的扩展。装饰者模式允许动态地为对象添加新功能,遵循开闭原则。在案例中,咖啡种类和调料作为装饰者,能够方便地增加或删除咖啡种类和调料选项,而无需修改原有代码。通过代码实现,展示了如何创建抽象Drink类、咖啡类、装饰者类以及具体的调料装饰者类,以及如何通过装饰者模式计算不同组合的咖啡价格和描述。
摘要由CSDN通过智能技术生成

装饰者模式

星巴克咖啡订单项目

星巴克咖啡订单项目(咖啡馆):

  1. 咖啡种类/单品咖啡:Espresso(意大利浓咖啡)、ShortBlack、LongBlack(美式

咖啡)、Decaf(无因咖啡)

  1. 调料:Milk、Soy(豆浆)、Chocolate

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

  3. 使用OO的来计算不同种类咖啡的费用:客户可以点单品咖啡,也可以单品咖啡+调料组合

传统思路:

image-20211112171624630

问题:会发生类爆炸;

image-20211112171759534

问题:可以控制类的数量;增删调料种类不方便;

装饰者模式:

装饰者模式定义
  1. 装饰者模式:动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)
  2. 这里提到的动态的将新功能附加到对象ocp****原则,在后面的应用实例上会以代码的形式体现,请同学们注意体会。

image-20211115100245584

装饰者模式解决咖啡订单问题:

代码:

抽象的 drink 类:

@Data
public abstract class Drink {

    public  String des;
    private  float price = 0.0f;

    //抽象方法:计算价格,由子类实现
    public abstract float cost();

}

咖啡类及各种单品咖啡:

//继承drink,并作为其他单品咖啡的父类(抽象出的父类)
public class Coffee extends Drink {

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

}

//继承咖啡类——具体的单品咖啡
//意大利咖啡
public class Espresso extends  Coffee {
    public Espresso(){
        setDes("意大利咖啡");
        setPrice(6.0f);
    }
}
//奥式黑咖啡
public class LongBlack extends  Coffee{
    public  LongBlack(){
        setDes(" Long black");
        setPrice(5.0f);
    }
}

装饰者:

//抽象出的装饰者父类
public class Decorator extends Drink {

    private Drink obj;

    public Decorator(Drink obj){
        this.obj = obj;
    }

    @Override
    public float cost() {
        //getPrice 自己的价格 + 组合的饮品价格
        return super.getPrice() + obj.cost();
    }

    @Override
    public String getDes() {
        //输出了被装饰者 drink 的信息
        return super.des + " "+ super.getPrice() + "&&" + obj.getDes();
    }

}

//具体的调味品装饰者
//巧克力 这里就是调味品
public class Chocolate extends  Decorator{
    public Chocolate(Drink obj) {
        super(obj);
        setDes("巧克力");
        setPrice(3.0f);
    }
}
//装饰者 牛奶
public class Milk extends Decorator{
    public Milk(Drink obj) {
        super(obj);
        setDes("牛奶");
        setPrice(2);
    }
}

测试:

public class CoffeeBar {
    public static void main(String[] args) throws Exception {
        //1.点一份 long black
        Drink order = new LongBlack();
        System.out.println("费用1:"+order.cost());//费用1:5.0
        System.out.println("描述1:"+order.getDes());//描述1: Long black
        //2.加入一份牛奶,让牛奶 装饰 源drink
        order = new Milk(order);
        System.out.println("加入牛奶,费用2:"+order.cost());//加入牛奶,费用2:7.0
        System.out.println("加入牛奶,描述2:"+order.getDes());//加入牛奶,描述2:牛奶 2.0&& Long black
        //3.再加入一份巧克力
        order = new Chocolate(order);
        System.out.println("加入牛奶,加入1份巧克力,费用:"+order.cost());//加入牛奶,加入1份巧克力,费用:10.0
        System.out.println("加入牛奶,加入1份巧克力,描述:"+order.getDes());//加入牛奶,加入1份巧克力,描述:巧克力 3.0&&牛奶 2.0&& Long black
        //4.在加入一份巧克力
        order = new Chocolate(order);
        System.out.println("加入牛奶,有加入2份巧克力,费用:"+order.cost());//加入牛奶,有加入2份巧克力,费用:13.0
        System.out.println("加入牛奶,有加入2份巧克力,描述:"+order.getDes());//加入牛奶,有加入2份巧克力,费用:13.0
//        DataInputStream dataInputStream =new DataInputStream(new FileInputStream("d:\\a.txt"));
    }
}
  • 把需要装饰的事物和装饰的事物抽象成同一大类(Drink)作为共同父类;装饰者中组合这一抽象父类,以便后续不断包裹装饰;

jdk中应用:

image-20211115105623255

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值