尚硅谷设计模式学习(九)装饰者模式

以咖啡订单引入装饰者模式

  • 咖啡种类:Espresso(意大利浓咖啡)、ShortBlack、LongBlack(美式咖啡)、Decaf(无因咖啡)
  • 调料:Milk、Soy(豆浆)、Chocolate

客户可以点单品咖啡,也可以单品咖啡+调料组合。

方案一

比较差的设计样例,耦合度过高。

如果说要添加扩展新的单品咖啡或者组合口味的咖啡,类的数量增加,就会引发"类爆炸"。

 方案二

将调料内置到Drink类,不会造成类数量过多。

但是,添加或者删除调味品的种类时,需要改动维护。

一、装饰者模式 

1、基本介绍

动态的将新功能附加到对象上

在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)。

装饰者模式原理

装饰者模式就像打包一个快递

  • 主体:比如:陶瓷、衣服    (Component) //    被装饰者 
  • 包装:比如:报纸填充、塑料泡沫、纸板、木板(Decorator) 

Component 主体:比如类似前面的  Drink

ConcreteComponent:具体的主体, 比如前面的各个单品咖啡

Decorato:装饰者,比如各调料

如果  ConcreteComponent  类很多,还可以设计一个缓冲层,将共有的部分提取出来,抽象成一个类。

2、代码实现 

思路分析

在这里插入图片描述  

抽象类饮品

public abstract class Drink {
    //对饮品的描述
    private String description;
    //价格
    private float price;

    //计算价格,由子类实现
    public abstract float cost();

    public void setDescription(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }

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

    public float getPrice() {
        return price;
    }
}

缓冲类Coffee

public class Coffee extends Drink{
    @Override
    public float cost() {
        return super.getPrice();
    }
}

两种Coffee

public class LongBlackCoffee extends Coffee{
    public LongBlackCoffee(){
        setDescription("一份美式咖啡");
        setPrice(7.0f);
    }
}
public class ShortBlackCoffee extends Coffee {
    public ShortBlackCoffee(){
        setDescription("一份浓缩咖啡");
        setPrice(5.0f);
    }
}

装饰者Decorator

//装饰者
public class Decorator extends Drink{
    //被装饰者;
    private Drink drink;

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

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

    @Override
    public String getDescription(){
        return drink.getDescription() + " && " +
                super.getDescription() + super.getPrice();
    }
}

两种调味品

public class Milk extends Decorator{
    public Milk(Drink drink) {
        super(drink);
        setDescription("一份牛奶");
        setPrice(2.0f);
    }
}
public class Chocolate extends Decorator{
    public Chocolate(Drink drink) {
        super(drink);
        setDescription("一份巧克力");
        setPrice(1.0f);
    }
}

模拟客户下单

public class Client {
    public static void main(String[] args) {
        //两份巧克力+一份牛奶的美式咖啡;
        //1.先点美式咖啡;
        Drink result = new LongBlackCoffee();
        System.out.println("步骤一::" + result.getDescription());
        System.out.println("本次花费==>" + result.cost());

        //2.加份牛奶;
        result = new Milk(result);
        System.out.println("步骤二::" + result.getDescription());
        System.out.println("本次花费==>" + result.cost());

        //3.加份巧克力;
        result = new Chocolate(result);
        System.out.println("步骤三::" + result.getDescription());
        System.out.println("本次花费==>" + result.cost());

        //4.加份巧克力;
        result = new Chocolate(result);
        System.out.println("步骤四::" + result.getDescription());
        System.out.println("最终花费==>" + result.cost());
    }
}

输出

步骤一::一份美式咖啡
本次花费==>7.0
步骤二::一份美式咖啡 && 一份牛奶2.0
本次花费==>9.0
步骤三::一份美式咖啡 && 一份牛奶2.0 && 一份巧克力1.0
本次花费==>10.0
步骤四::一份美式咖啡 && 一份牛奶2.0 && 一份巧克力1.0 && 一份巧克力1.0
最终花费==>11.0

 二、装饰者模式在 JDK 应用的源码分析

Java 的 IO  结构,FilterInputStream  就是一个装饰者

public class Test {
    public static void main(String[] args) throws IOException {
        DataInputStream dataInputStream = new DataInputStream(new FileInputStream("e:\\a.txt"));
        System.out.println(dataInputStream.read());
        dataInputStream.close();
    }
}

说明

  • InputStream 是抽象类,类似前面的Drink
  • FileInputStream是InputStream子类,类似前面的浓缩咖啡,美式咖啡
  • FilterInputStream是InputStream子类,类似前面的Decorator修饰者
  • DataInputStream是FilterInputStream子类,具体的修饰者,类似前面的Milk,Chocolate等
  • FilterInputStream类有protected  volatile InputStream  in; 即含被装饰者
public class FilterInputStream extends InputStream {
    protected volatile InputStream in;

    protected FilterInputStream(InputStream var1) {
        this.in = var1;
    }

分析得出在 JDK 的 IO 体系中,就是使用装饰者模式 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小鲁蛋儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值