Java设计模式(八)——————【结构型模式】设计模式之装饰者模式

源码地址:https://github.com/877148107/java-design-pattern

  • 基本介绍

  1. 装饰者模式:动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)

  2. 这里提到的动态的将新功能附加到对象ocp****原则,在后面的应用实例上会以代码的形式体现。

  • 基本原理

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

    主体:比如:陶瓷、衣服 (Component) // 被装饰者

    包装:比如:报纸填充、塑料泡沫、纸板、木板(Decorator)

  2. Component主体

  3. ConcreteComponent:具体的主体,Decorator: 装饰者

  4. 在如图的ComponentConcreteComponent之间,如果ConcreteComponent类很多,还可以设计一个缓冲层,将共有的部分提取出来,抽象层一个类。

在这里插入图片描述

  • 案例说明

    1、需求

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

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

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

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

2、UML类图

1)Drink就是一个被装饰类(主体)就是前面说的抽象类, Component,

2)ShortBlack 就单品咖啡

3)Decorator 是一个装饰类,含有一个被装饰的对象(Drink obj)

4)Decorator 的cost 方法 进行一个费用的叠加计算,递归的计算价格

Drink就是需求中的咖啡,coffee就是具体美式咖啡、意大利浓咖啡等的父类,Decorator装饰咖啡的在咖啡里面加牛奶、巧克力等。这里Coffee和Decorator就代表了具体的被装饰者和具体的装饰着。

在这里插入图片描述

3、代码实现

被装饰类(主体)

public abstract class Drink {

    /**
     * 描述
     */
    private String description;

    /**
     * 单价
     */
    private float price;

    /**
     * 抽象方法,子类实现计算费用
     * @return
     */
    public abstract float cost();

    public String getDescription() {
        return description;
    }

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

    public float getPrice() {
        return price;
    }

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

装饰类,包含了被装饰类

public class Decorator extends Drink {

    Drink drink;

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

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

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

class Milk extends Decorator{
    public Milk(Drink drink) {
        super(drink);
        setDescription("一份牛奶");
        setPrice(5f);
    }
}

class Chocolate extends Decorator{
    public Chocolate(Drink drink) {
        super(drink);
        setDescription("一份巧克力");
        setPrice(2f);
    }
}

具体的被装饰类(具体的主体)

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

class Espresso extends Coffee{
    public Espresso() {
        setDescription("意大利浓咖啡");
        setPrice(5f);
    }
}

class ShortBlack extends Coffee{
    public ShortBlack() {
        setDescription("浓咖啡");
        setPrice(4f);
    }
}

class LongBlack extends Coffee{
    public LongBlack() {
        setDescription("美式咖啡");
        setPrice(6f);
    }
}

测试

public class CoffeeClient {

    public static void main(String[] args) {
        Drink longBlack = new LongBlack();
        System.out.println("描述:"+longBlack.getDescription());
        System.out.println("价格:"+longBlack.cost());
        System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
        Drink espresso = new Espresso();
        System.out.println("描述:"+espresso.getDescription());
        System.out.println("价格:"+espresso.cost());
        System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
        System.out.println("=====美式咖啡+一份牛奶+两份巧克力======");
        longBlack = new Milk(longBlack);
        longBlack = new Chocolate(longBlack);
        longBlack = new Chocolate(longBlack);
        System.out.println("描述:"+longBlack.getDescription());
        System.out.println("加一份牛奶,两份巧克力价格:"+longBlack.cost());
        System.out.println("=====意大利浓咖啡+一份牛奶+一份巧克力======");
        espresso = new Milk(espresso);
        espresso = new Chocolate(espresso);
        System.out.println("描述:"+espresso.getDescription());
        System.out.println("加一份牛奶,一份巧克力价格:"+espresso.cost());

    }
}

在这里插入图片描述

  • JDK源码分析

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

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

    1、InputStream就是一个抽象类,跟前面案例的drink一样

    2、FileInputStream是InputStream子类,类似前面案例的LongBlack、Espresso

    3、FilterInputStream是InputStream子类,类似前面案例的Decorator,里面包含了被装饰着InputStream

    4、DataInputStream是FilterInputStream子类,类似前面的Milk、Chocolat

在这里插入图片描述

public abstract class InputStream implements Closeable {
    public abstract int read() throws IOException;
}
public class FilterInputStream extends InputStream {
    /**
     * The input stream to be filtered.
     */
    protected volatile InputStream in;

    /**
     * Creates a <code>FilterInputStream</code>
     * by assigning the  argument <code>in</code>
     * to the field <code>this.in</code> so as
     * to remember it for later use.
     *
     * @param   in   the underlying input stream, or <code>null</code> if
     *          this instance is to be created without an underlying stream.
     */
    protected FilterInputStream(InputStream in) {
        this.in = in;
    }
}
public class DataInputStream extends FilterInputStream implements DataInput {
    public DataInputStream(InputStream in) {
        super(in);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值