装饰者模式——配合Java源码进行深入讲解(一)

本文先从装饰者模式的内容进行讲解,然后深入到java源码中用到装饰者模式的内容中去。

首先,使用head first设计模式书中的一个例子进行装饰者模式的讲解。

现在有一个名为Beverage(饮料)的抽象类,cost用于计算饮料各种调料的总费用。

public abstract class Beverage {
    protected String description = "beverage";

    public abstract double cost();

    public String getDescription() {
        return description;
    }
}

饮料有很多种类,有蓝山咖啡、浓缩咖啡等,而不同的饮料所添加的调料也各不相同,有摩卡、奶油等。

此时让你算出各种饮料的花费,你会怎么做?

很多人会先想到继承的方式,每有一种饮料就写一个类继承抽象类,每个类中都有各自不同的cost方法,用于计算自己调料的总费用。但是这样会有什么问题呢?如果我有很多种饮料,很容易造成类爆炸。

那么更进一步呢,有人想可以设计一个超类继承抽象类,在超类中放入所有调料的成员变量并设置成布尔值,然后在cost方法中进行每种调料的判断和计算。这样子类在继承这个超类的时候只要设置调料的布尔值,cost方法就可以自动算出总费用了。
这的确解决了类爆炸的问题,但是又会带来新的问题。超类中包含了所有的调料,但是子类中并不是都需要这些调料,有些调料甚至根本不适合这种饮料,但是子类都继承过来了。而且还有一个很重要的问题就是没有遵循开闭原则,如果有新的调料出来,那就需要修改超类。

此时就轮到装饰者模式出场了,它将各种饮料看成被装饰者,各种调料看成装饰者,用各种调料去装饰饮料,类似下图所示,就好比俄罗斯套娃一般。
在这里插入图片描述
接下来我们来看看具体的实现:

public class DarkRoast extends Beverage{
    public DarkRoast() {
        description = "dark roast coffe";
    }

    @Override
    public double cost() {
        return 2;
    }
}

DarkRoast代表一种饮料,它本身的费用是2,它是被装饰者的身份。

public abstract class CondimentDecorator extends Beverage{
    @Override
    public abstract String getDescription();
}

CondimentDecorator类用于子类声明,继承该类的子类代表的就是装饰者的身份。

public class Mocha extends CondimentDecorator{
    Beverage beverage;

    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public double cost() {
        return 0.2 + beverage.cost();
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ", Mocha";
    }
}

Mocha类代表一种调料,它本身的费用是0.2,它是装饰者的身份。注意!这里很重要的一点是Mocha类中组合了Beverage类,它让代码变得更加灵活。因为继承是编译时静态决定的,而组合是运行时动态决定的。

public class Whip extends CondimentDecorator{
    Beverage beverage;

    public Whip(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public double cost() {
        return 0.1 + beverage.cost();
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ", Whip";
    }
}

再添加一个调料类Whip。

现在我们有了饮料和调料类了,是时候冲泡出一杯完整的咖啡了

public class DecoratorMain {
    public static void main(String[] args) {
        Beverage darkRoast = new DarkRoast();
        darkRoast = new Mocha(darkRoast);
        darkRoast = new Whip(darkRoast);
        System.out.println(darkRoast.getDescription() + ", 费用:" + darkRoast.cost());
    }
}

//dark roast coffe, Mocha, Whip, 费用:13.0

从上面代码中可以看到,给饮料加调料十分地方便,只需new一个调料类,然后传入被装饰对象就可以了。如果觉得不便理解的同学,可以手动调试一下,看一下调用的过程,理解起来还是蛮简单的。

这是具体的uml类图
在这里插入图片描述
装饰者模式——配合Java源码进行深入讲解(二)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值