装饰器模式(Decorator Pattern)

定义

装饰者模式:动态地将责任附加到对象身上。若要扩展功能,将要比继承更加灵活,更富有弹性。

设计原则
  1. 封装变化。
  2. 少用继承,多用组合。
  3. 针对接口编程,不针对实现编程,更易于维护和扩展,更有条理。
  4. 交互对象之间的松耦合设计,是程序更具有弹性。
  5. 对扩展开放,对修改关闭
结构图

这里写图片描述

组成对象
  • 抽象组件角色(Component):定义一个对象接口,以规范准备接受附加责任的对象,即可以给这些对象动态地添加职责。
  • 具体组件角色(ConcreteComponent) :被装饰者,定义一个将要被装饰增加功能的类。可以给这个类的对象添加一些职责。
  • 抽象装饰器(Decorator):维持一个指向构件Component对象的实例,并定义一个与抽象组件角色Component接口一致的接口。
  • 具体装饰器角色(ConcreteDecoratorA,B…):向组件添加职责。
重点
  1. 装饰者和被装饰者(真实对象)具有相同的超类
  2. 可以有一个或者多个装饰者包装一个对象
  3. 可以用装饰者对象替代真实对象,可以在运行是动态的装饰对象
  4. 装饰者可以在真实对象执行自己的行为前/后加上自己的行为,达到特定目的
典型案例

下面就根据head first设计模式书中的例子,来看看星巴兹店是如何卖咖啡的。在计算不同组合的订单如何计算最终价格,以及出现新的调料或者咖啡品种,如何在不修改原有的代码基础上扩展程序——对扩展开发,对修改关闭

来看一下最终设计的类结构图

这里写图片描述

案例中对应的角色
1. 抽象组件角色(Component):Beverage
2. 具体组件角色(ConcreteComponent):DarkRoast、Decaf、Espresso、HouseBlend
3. 抽象装饰器(Decorator):CondimentDecorator
4. 具体装饰器角色(ConcreteDecoratorA,B…):Mocha、Soy、Whip

参考代码

饮料抽象类——Beverage

/**
 * 饮料抽象类
 * @author: Yang Gao
 * @date: 2017-4-6 下午2:45:31
 * @version: 1.0
 */
public abstract class Beverage {
    protected String description = "Unknow Beverage!";

    public String getDescription() {
        return description;
    }
    // 定义饮料的单价
    public abstract double cost();
}

具体实现类,真实对象,被装饰者,各种饮料类

/**
 * 饮料:深度烘焙
 * @author: Yang Gao
 * @date: 2017-4-6 下午3:46:20
 * @version: 1.0
 */
public class DarkRoast extends Beverage {
    public DarkRoast() {
        this.description = "DarkRoast";
    }
    public double cost() {
        return .99;
    }
}
/**
 * 饮料:低咖啡因
 * @author: Yang Gao
 * @date: 2017-4-6 下午2:51:22
 * @version: 1.0
 */
public class Decaf extends Beverage {
    public Decaf() {
        this.description = "Decaf";
    }
    @Override
    public double cost() {
        return 1.99d;
    }
}
/**
 * 饮料:浓咖啡
 * @author: Yang Gao
 * @date: 2017-4-6 下午2:51:22
 * @version: 1.0
 */
public class Espresso extends Beverage {
    public Espresso() {
        this.description = "Espresso";
    }
    @Override
    public double cost() {
        return 1.99d;
    }
}
/**
 * 饮料:混合
 * @author: Yang Gao
 * @date: 2017-4-6 下午3:47:58
 * @version: 1.0
 */
public class HouseBlend extends Beverage {
    public HouseBlend() {
        this.description = "House Blend Coffee";
    }
    public double cost() {
        return .89;
    }
}

装饰抽象类, 调料抽象类

/**
 * 调料抽象类:装饰饮料类
 * @author: Yang Gao
 * @date: 2017-4-6 下午2:45:31
 * @version: 1.0
 */
public abstract class CondimentDecorator extends Beverage{
    protected Beverage beverage;

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

    public abstract String getDescription();
}

具体装饰者

/**
 * 调料:摩卡
 * @author: Yang Gao
 * @date: 2017-4-6 下午2:53:53
 * @version: 1.0
 */
public class Mocha extends CondimentDecorator {
    public Mocha(Beverage beverage) {
        super(beverage);
    }
    @Override
    public String getDescription() {
        return super.beverage.getDescription() + ", Mocha";
    }
    @Override
    public double cost() {
        return .2d + super.beverage.cost();
    }
}
/**
 * 调料:豆浆
 * @author: Yang Gao
 * @date: 2017-4-6 下午2:53:53
 * @version: 1.0
 */
public class Soy extends CondimentDecorator {
    public Soy(Beverage beverage) {
        super(beverage);
    }
    @Override
    public String getDescription() {
        return super.beverage.getDescription() + ", Soy";
    }
    @Override
    public double cost() {
        return .15d + super.beverage.cost();
    }
}
/**
 * 调料:奶泡
 * @author: Yang Gao
 * @date: 2017-4-6 下午2:53:53
 * @version: 1.0
 */
public class Whip extends CondimentDecorator {
    public Whip(Beverage berevage) {
        super(berevage);
    }
    @Override
    public String getDescription() {
        return super.beverage.getDescription() + ", Whip";
    }
    @Override
    public double cost() {
        return .1d + super.beverage.cost();
    }
}

客户端测试类

/**
 * 咖啡店
 * @author: Yang Gao
 * @date: 2017-4-6 下午2:57:20
 * @version: 1.0
 */
public class StarbuzzCoffee {
    public static void main(String[] args) {
        // 1.来一杯浓咖啡
        Espresso beverage = new Espresso();
        System.out.println("一杯浓咖啡:" + beverage.getDescription() + ",  $" + beverage.cost());
        // 2.来一杯双倍摩卡奶泡深度烘焙
        Beverage beverage2 = new DarkRoast();
        beverage2 = new Mocha(beverage2);
        beverage2 = new Mocha(beverage2);
        beverage2 = new Whip(beverage2);
        System.out.println("一杯双倍摩卡奶泡深度烘焙:" + beverage2.getDescription() + ",  $" + beverage2.cost());
        // 3.来一杯摩卡奶泡豆浆混合
        Beverage beverage3 = new HouseBlend();
        beverage3 = new Soy(beverage3);
        beverage3 = new Mocha(beverage3);
        beverage3 = new Whip(beverage3);
        System.out.println("一杯摩卡奶泡豆浆浓混合:" + beverage3.getDescription() + ",  $" + beverage3.cost());       
}

运行结果

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值