设计模式(四)--装饰者模式(Decorator/Wrapper Pattern)

咖啡店的需求

你的项目组最近接到一个项目,要为一家咖啡店升级订单系统,原有设计如下

代码如下:

/**
 * 饮料的基类,所有饮料继承该接口
 */
public interface Beverage {
    String getDescription();

    double cost();
}
public class Espresso implements Beverage {
    @Override
    public String getDescription() {
        return "美式咖啡";
    }

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

现在咖啡店想要给咖啡加调料,根据调料不同,显示的描述不同,价格也不同,应该如何设计系统呢?

新的设计

根据需求,其实就是在原有类上加强功能,并且功能是可以灵活组合的,比如可以加奶,加豆浆,或者加双倍的奶,这就可以使用装饰者模式

装饰者模式的特点是:向一个现有的对象添加新的功能,同时又不改变其结构。属于对象结构型模式。

创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能

CondimentDecorator是加调料的装饰类,之所以要继承Beverage,是为了继承其类型,这样使用饮料的地方就能用这个装饰者来代替

下面看下装饰类的实现

/**
 * 调味品装饰基类
 */
public abstract class CondimentDecorator implements Beverage {
    protected Beverage beverage;

    /**
     * 每个装饰类需要传入真正的饮料
     */
    public CondimentDecorator(Beverage beverage) {
        this.beverage = beverage;
    }
}
public class Milk extends CondimentDecorator {
    public Milk(Beverage beverage) {
        super(beverage);
    }

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

    @Override
    public double cost() {
        // 加奶多两元
        return beverage.cost() + 2;
    }
}
public class Soy extends CondimentDecorator {

    public Soy(Beverage beverage) {
        super(beverage);
    }

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

    @Override
    public double cost() {
        // 豆浆加3元
        return beverage.cost() + 3;
    }
}

可以看到装饰类都需要传入真正的饮料,也就是被装饰的对象,然后在其基础上做功能的加强

测试一下代码,发现可正确计算出价格

public class MainTest {
    public static void main(String[] args) {
        // 要一杯浓缩咖啡,加奶加豆浆
        Beverage coffe = new Espresso();
        coffe = new Milk(coffe);
        coffe = new Soy(coffe);
        System.out.println(coffe.getDescription());
        System.out.println(coffe.cost());

        // 要一杯焦炒咖啡,加双倍奶加豆浆
        Beverage coffe1 = new DarkRoast();
        coffe1 = new Milk(coffe1);
        coffe1 = new Milk(coffe1);
        coffe1 = new Soy(coffe1);
        System.out.println(coffe1.getDescription());
        System.out.println(coffe1.cost());
    }
}

输出:

美式咖啡,加奶,加豆浆
17.0
焦炒咖啡,加奶,加奶,加豆浆
22.0

扩展

看类图可以看到装饰者模式和代理模式挺像的,装饰器和代理之间的区别很细微,可以认为装饰器是代理的一个子集。静态代理就是装饰器的方式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值