设计模式——装饰者模式
2015-12-21 14:01
344 查看
装饰者模式主要体现了OO原则中的“对扩展开放,对修改关闭”这条原则。
装饰者模式主要有一下特点:
1 装饰者和被装饰对象有相同的超类型;
2 你可以用一个或多个装饰者包装一个对象;
3既然装饰者和被装饰对象有相同的超类型,所以在任何需要原始对象(被包装的)的场合,可以使用装饰过的对象代替它;
4装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的;
5对象可以在任何时候被装饰,所以可以在运行时动态地,不限量地用你喜欢的装饰者来修饰对象。
装饰者模式的定义:
动态地将责任附加到对象上。若要扩展功能,装饰者提供比继承更具有弹性的代替方案。
使用场景举例:星巴克咖啡的订单系统,一种咖啡(比如,综合、深焙、低咖啡因、浓缩)可以加入多种调料(牛奶、摩卡、豆浆、奶泡),比如顾客想要一杯双倍摩卡豆浆奶泡咖啡,或者牛奶摩卡浓缩咖啡,在这个场景中,基础的咖啡属于被装饰者,而各种调料属于装饰者。
根据装饰者的特性(装饰者和被装饰对象有相同的超类型)所以首先定义一个抽象的Beverage类,这是饮料和调料的基类,饮料和调料都会继承这个抽象类。
基类中有一个饮料描述的属性,和一个计算价格的抽象方法,同时还有一个获取描述的getDescription方法
在声明一个所有调料的抽象类,也就是装饰者类,注意这里是调料!
CondimentDecorator 继承自Beverage 从而满足装饰者和被装饰对象有相同的超类型。
现在具体来实现一种饮料吧,以浓缩咖啡为例
现在是各种调料的具体实现
摩卡的
豆浆的
奶泡的
测试一下,比如现在顾客想要一杯甚么都不加的浓缩咖啡,代码如下:
打印结果
再来一杯摩卡奶泡的浓缩咖啡
打印结果
由以上例子可以看出装饰者模式巧妙的运用了组合和委托的方式,达到在运行时动态的加上新行为;你可以用无数个装饰者包装一个对象;装饰者的缺点同时也是显而易见的,那就是使用装饰者模式会导致设计中出现许多小对象,如果过度使用,会让程序变得很复杂,所以在实际使用过程中可以使用装饰者模式+工厂模式的组合形式。
装饰者模式主要有一下特点:
1 装饰者和被装饰对象有相同的超类型;
2 你可以用一个或多个装饰者包装一个对象;
3既然装饰者和被装饰对象有相同的超类型,所以在任何需要原始对象(被包装的)的场合,可以使用装饰过的对象代替它;
4装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的;
5对象可以在任何时候被装饰,所以可以在运行时动态地,不限量地用你喜欢的装饰者来修饰对象。
装饰者模式的定义:
动态地将责任附加到对象上。若要扩展功能,装饰者提供比继承更具有弹性的代替方案。
使用场景举例:星巴克咖啡的订单系统,一种咖啡(比如,综合、深焙、低咖啡因、浓缩)可以加入多种调料(牛奶、摩卡、豆浆、奶泡),比如顾客想要一杯双倍摩卡豆浆奶泡咖啡,或者牛奶摩卡浓缩咖啡,在这个场景中,基础的咖啡属于被装饰者,而各种调料属于装饰者。
根据装饰者的特性(装饰者和被装饰对象有相同的超类型)所以首先定义一个抽象的Beverage类,这是饮料和调料的基类,饮料和调料都会继承这个抽象类。
public abstract class Beverage { String description = "Unknown Beverage"; public String getDescription() { return description; } public abstract double cost(); }
基类中有一个饮料描述的属性,和一个计算价格的抽象方法,同时还有一个获取描述的getDescription方法
在声明一个所有调料的抽象类,也就是装饰者类,注意这里是调料!
public abstract class CondimentDecorator extends Beverage { public abstract String getDescription(); }
CondimentDecorator 继承自Beverage 从而满足装饰者和被装饰对象有相同的超类型。
现在具体来实现一种饮料吧,以浓缩咖啡为例
public class Espresso extends Beverage {//继承自Beverage因为Espresso是一种饮料 public Espresso() { // TODO Auto-generated constructor stub description = "Espresso";//设置饮料的描述,这里使用了构造器,或者你也可以使用setter方法。 } @Override public double cost() { // TODO Auto-generated method stub return 1.99;//返回Espresso的价格 } }
现在是各种调料的具体实现
摩卡的
public class Mocha extends CondimentDecorator {//继承自CondimentDecorator保证相同的超类型。 Beverage beverage;//记录饮料。 public Mocha(Beverage beverage) { // TODO Auto-generated constructor stub this.beverage = beverage; } @Override public String getDescription() { // TODO Auto-generated method stub return beverage.getDescription() + ",Mocha";//完整的饮料描述。 } @Override public double cost() { // TODO Auto-generated method stub return .20 + beverage.cost();//返回带摩卡的咖啡饮料价钱 } }
豆浆的
public class Soy extends CondimentDecorator { Beverage beverage; public Soy(Beverage beverage) { // TODO Auto-generated constructor stub this.beverage = beverage; } @Override public String getDescription() { // TODO Auto-generated method stub return beverage.getDescription() + ",soy"; } @Override public double cost() { // TODO Auto-generated method stub return .15 + beverage.cost(); } }
奶泡的
package com.design.patterns.decorator; public class Whip extends CondimentDecorator { Beverage beverage; public Whip(Beverage beverage) { // TODO Auto-generated constructor stub this.beverage = beverage; } @Override public String getDescription() { // TODO Auto-generated method stub return beverage.getDescription() + ",whip"; } @Override public double cost() { // TODO Auto-generated method stub return .10 + beverage.cost(); } }
测试一下,比如现在顾客想要一杯甚么都不加的浓缩咖啡,代码如下:
public class StarbuzzCoffee { public static void main(String[] args) { // TODO Auto-generated method stub Beverage beverage=new Espresso();//订一杯Espresso,不需要调料。 System.out.println(beverage.getDescription()+" $"+beverage.cost());//打印描述与价格 } }
打印结果
Espresso $1.99
再来一杯摩卡奶泡的浓缩咖啡
public class StarbuzzCoffee { public static void main(String[] args) { // TODO Auto-generated method stub Beverage beverage=new Espresso();//浓缩咖啡 beverage=new Mocha(beverage);//用摩卡装饰它 beverage=new Whip(beverage);//用奶泡装饰它 System.out.println(beverage.getDescription()+" $"+beverage.cost());//打印描述和价格 } }
打印结果
Espresso,Mocha,whip $2.29
由以上例子可以看出装饰者模式巧妙的运用了组合和委托的方式,达到在运行时动态的加上新行为;你可以用无数个装饰者包装一个对象;装饰者的缺点同时也是显而易见的,那就是使用装饰者模式会导致设计中出现许多小对象,如果过度使用,会让程序变得很复杂,所以在实际使用过程中可以使用装饰者模式+工厂模式的组合形式。
相关文章推荐
- 阿里 vs. 腾讯,谁的收购更有眼光?
- 数据库_Mysql _Every derived table must have its own alias 错误 子查询出来的表必须有一个临时表名
- SpringMVC内容概要
- Duilib开发手机助手基础教程
- C++空类默认函数(编译器处理)
- 合理利用“泛在式” - 手机促使人群分化
- 123,数组的读写
- 很多k线形态或k线组合是需要验证的
- 解决setTimeout 计时器重复调用的问题
- viewWithTag
- Windows上简单配置端口转发
- Could not load file or assembly 'MySql.Data.CF,
- Javascript中null值,特别注意的两点
- CentOS 5.11开启VNC访问
- Eclipse中使用maven问题汇总
- 定义了浮动元素后margin-bottom失效的解决办法
- css3 常用命令总结(不定期更新)
- JAVASCRIPT中NULL值,特别注意的两点
- Python的Socket学习
- mysql运行参数详解