装饰器模式(Decorator Pattern)
来源:互联网 发布:西安程序员工资 编辑:程序博客网 时间:2024/05/29 05:54
定义
装饰者模式:动态地将责任附加到对象身上。若要扩展功能,将要比继承更加灵活,更富有弹性。
设计原则
- 封装变化。
- 少用继承,多用组合。
- 针对接口编程,不针对实现编程,更易于维护和扩展,更有条理。
- 交互对象之间的松耦合设计,是程序更具有弹性。
- 对扩展开放,对修改关闭
结构图
组成对象
- 抽象组件角色(Component):定义一个对象接口,以规范准备接受附加责任的对象,即可以给这些对象动态地添加职责。
- 具体组件角色(ConcreteComponent) :被装饰者,定义一个将要被装饰增加功能的类。可以给这个类的对象添加一些职责。
- 抽象装饰器(Decorator):维持一个指向构件Component对象的实例,并定义一个与抽象组件角色Component接口一致的接口。
- 具体装饰器角色(ConcreteDecoratorA,B…):向组件添加职责。
重点
- 装饰者和被装饰者(真实对象)具有相同的超类
- 可以有一个或者多个装饰者包装一个对象
- 可以用装饰者对象替代真实对象,可以在运行是动态的装饰对象
- 装饰者可以在真实对象执行自己的行为前/后加上自己的行为,达到特定目的
典型案例
下面就根据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
- 装饰器模式(Decorator Pattern)
- 装饰器模式(Decorator Pattern)
- 装饰器模式(Decorator Pattern)
- 装饰器模式(Decorator Pattern)
- 装饰模式(Decorator Pattern)
- 装饰模式(Decorator Pattern)
- 装饰模式(Decorator Pattern)
- 装饰模式(Decorator Pattern)
- 装饰模式(Decorator Pattern)
- 装饰模式(Decorator Pattern)
- 装饰模式(Decorator Pattern)
- 装饰模式Decorator Pattern
- 装饰模式(Decorator Pattern)
- 装饰模式(Decorator Pattern)
- 装饰模式--Decorator pattern
- 装饰模式 Decorator Pattern
- 装饰模式【DECORATOR PATTERN 】
- 装饰模式【Decorator Pattern】
- php Imagick制作个性二维码的方法
- jquery.cookie() 设置过期时间 (自己记录使用)
- 小莫的成神之旅(一)原生js封装组件tooltip
- 单元测试:java.lang.IllegalStateException: Failed to load ApplicationContext
- cout<<重载,将定义置于头文件中发生错误(未解)
- 装饰器模式(Decorator Pattern)
- ESP8266 MAC(OSX)开发环境搭建
- JSON初认识
- java 101-200之间的素数
- HDU 5742 It's All In The Mind 贪心
- Android实战之app版本更新升级全文章(三)
- mysql按周统计数据
- 数据库<3>
- POJ1751 Highways