设计模式 之 装饰者(Decorator)模式
装饰者模式(Decorator):动态地为一个对象添加一些额外的职责,若要扩展一个对象的功能,装饰者提供了比继承更有弹性的替代方案。
结构图:

- 抽象构件类(Component):给出一个抽象的接口,用以规范准备接收附加责任的对象
- 具体构件类(ConcreteComponent):定义一个具体的准备接受附加责任的类,其必须实现Component接口。
- 装饰者类(Decorator):持有一个构件(Conponent)对象的实例,并定义一个和抽象构件一致的接口。
- 具体装饰者类(Concrete Decoratator):定义给构件对象“贴上”附加责任。
下面用一个实例来讲解一下装饰者模式《head first 设计模式》中的例子:比如在星巴兹咖啡馆,人们需要根据自己的爱好来订购咖啡,而具体的coffee种类假设一共用两类:HouseBlend(混合咖啡)和darkRoast(深焙咖啡)。而另外客人也可根据的口味来添加一些其他的东西,例如:摩卡(mocha)、Milk(牛奶)。
从实例中可以分析出:抽象构件类对应的就是coffee饮品(下面的beverage类),具体构件类对应的就是HouseBlend和darkRoast;具体装饰者类对应mocha和milk口味;至于装饰者类这里没有对应,主要用于具体装饰者类的继承。下面看具体d
源代码:
抽象构件类(Component):
Beverage.java:
/**
* @author haifei
* 抽象构件类
*/
public abstract class Beverage { String description = "未知的咖啡"; public String getDescription(){
return description;
} public abstract double cost();
}
具体构件类(ConcreteComponent):
DarkRoast.java:
/**
* @author haifei
* 具体构件类
*/
public class DarkRoast extends Beverage{ public DarkRoast(){
description = "深焙咖啡";
} @Override
public double cost() {
return 1.0;
} }
HouseBlend.java:
/**
* @author haifei
* 具体构件类。HouseBlend代表咖啡中的一种:混合咖啡
*/
public class HouseBlend extends Beverage{ public HouseBlend() {
description = "混合咖啡";
} @Override
public double cost() {
return .89;
} }
装饰者类(Descorator):
ConimentDecorator.java:
/**
* @author haifei
* 抽象装饰者类,所有的具体装饰者都必须继承这个类
*/
public abstract class CondimentDecorator extends Beverage{ public abstract String getDescription(); }
具体装饰者类(ConcreteDescorator):
Mocha.java:
public class Mocha extends CondimentDecorator{
Beverage beverage;
public Mocha(Beverage beverage){
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ",摩卡";
}
@Override
public double cost() {
return beverage.cost() + .20;
}
}
Milk.java:
public class Milk extends CondimentDecorator{
Beverage beverage;
public Milk(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + " ,牛奶";
}
@Override
public double cost() {
return beverage.cost() + .10;
}
}
客户端(Client):
StarBuzzCoffee.java:
public class StarBuzzCoffee {
public static void main(String[] args){
Beverage beverage1 = new DarkRoast();
beverage1 = new Milk(beverage1);
beverage1 = new Mocha(beverage1);
System.out.println(beverage1.getDescription() + "$" + beverage1.cost());
Beverage beverage2 = new HouseBlend();
beverage2 = new Milk(beverage2);
beverage2 = new Mocha(beverage2);
System.out.println(beverage2.getDescription() + "$" + beverage2.cost());
}
}
运行结果:
深焙咖啡 ,牛奶,摩卡$1.3
混合咖啡 ,牛奶,摩卡$1.19
设计模式 之 装饰者(Decorator)模式的更多相关文章
- Head First 设计模式 —— 03. 装饰器 (Decorator) 模式
思考题 有如下类设计: 如果牛奶的价钱上扬,怎么办?新增一种焦糖调料风味时,怎么办? 造成这种维护上的困难,违反了我们之前提过的哪种设计原则? P82 取出并封装变化的部分,让其他部分不收影响 多用组 ...
- 设计模式之装饰(Decorator)模式
设计模式之装饰(Decorator)模式 (一)什么是装饰(Decorator)模式 装饰模式,又称为包装模式,它以对客户端透明的方式扩张对象的功能,是继承关系的替代方案之一. 装饰模式可以在不使用创 ...
- java设计模式03装饰者者模式
动态地给一个对象添加一些额外的职责.就增加功能来说, Decorator模式相比生成子类更为灵活.该模式以对客 户端透明的方式扩展对象的功能. (1)在不影响其他对象的情况下,以动态.透明的方式给单个 ...
- 设计模式之装饰(Decorator)模式 代码详解
/** * Created with IntelliJ IDEA. * User: HYY * Date: 13-10-27 * Time: 下午10:49 * To change this temp ...
- 装饰器(Decorator)模式
public interface IDoThings { public void doSomeThing(); } public class DoThings implements IDoThings ...
- JS 设计模式九 -- 装饰器模式
概念 装饰者(decorator)模式能够在不改变对象自身的基础上,动态的给某个对象添加额外的职责,不会影响原有接口的功能. 模拟传统面向对象语言的装饰者模式 //原始的飞机类 var Plane = ...
- 学习javascript设计模式之装饰者模式
1.装饰者模式定义:给对象动态添加职责的方式称为装饰者(decorator)模式. js如何实现装饰者模式 通过保存原函数引用方式改写某函数 window.onload = function(){al ...
- C#设计模式(9)——装饰者模式(Decorator Pattern)
一.引言 在软件开发中,我们经常想要对一类对象添加不同的功能,例如要给手机添加贴膜,手机挂件,手机外壳等,如果此时利用继承来实现的话,就需要定义无数的类,如StickerPhone(贴膜是手机类).A ...
- [设计模式] 9 装饰者模式 Decorator
转:http://www.jellythink.com/archives/171#prettyPhoto 什么是装饰模式? 在GOF的<设计模式:可复用面向对象软件的基础>一书中对装饰模式 ...
- 设计模式的征途—10.装饰(Decorator)模式
虽然目前房价依旧很高,就连我所在的成都郊区(非中心城区)的房价均价都早已破万,但却还是阻挡不了大家对新房的渴望和买房的热情.如果大家买的是清水房,那么无疑还有一项艰巨的任务在等着大家,那就是装修.对新 ...
随机推荐
- 30天C#基础巩固-----值类型/引用类型,泛型,空合并操作符(??),匿名方法
一:值类型/引用类型的区别 值类型主要包括简单类型,枚举类型,和结构体类型等,值类型的实例通常被分配在线程堆栈上面变量保存的内容是实例数据本身.引用类型被分配在托管堆上,变量保存的是地址.引 ...
- 完美且精准的 IE10- 版本检测。
通过动态的写入条件注释的方式,来判断当前的ie浏览器的版本,优点是,对比userAgent字符匹配,要精准很多,应该说是100%正确,缺点就是要通过JS写入条件注释,拖慢页面的加载速度. 如果对于只判 ...
- 【转】同一台Windows机器中启动多个Memcached服务
上一篇介绍了Memcached的安装,但是如果手头上只有一台机器,又想做多节点测试咋办? 这就需要在一台机器上启动多个Memcached服务了. 假设Memcached在如下目录:C:\memcach ...
- foreach DataTable或Table时要略过第一行。
昨天有续写一个练习<输入数字动态创建行(二)>http://www.cnblogs.com/insus/p/4916260.html ,最终是需要把数据存入数据库中. 在循环ASP:Tab ...
- 关于CodeFirst异常:无法确定类型'XXX'和类型‘YYY’之间的关联的主体端,必须使用关系 Fluent API 或数据注释显式配置此关联的主体端。
此错误的原因是,你配置两个实体间的关系为一对一 然而我认为的一对一关系是,两者之间必须存在一个主体, 也就是说,你不能表1的外键是表2的主键并且表1的主键是表2的外键, 这样不符合数据库式吧? 我想多 ...
- 温故而知新--sql存储过程复习
存储过程是已编译好的T-SQL语句的集合,可以随时调用,速度快,不易出错. 可以传递参数,普通参数和输出参数(output) 实例1 create proc Newpro @testVarA int, ...
- lua学习之table类型
关系表类型,这是一个很强大的类型.我们可以把这个类型看作是一个数组.只是 C语言的数组,只能用正整数来作索引: 在Lua中,你可以用任意类型的值来作数组的索引,但这个值不能是 nil.同样,在C语言中 ...
- Oracle中添加新用户并赋予权限
--创建一个新用户NewUser 并设置密码为1 create user NewUser identified by 1; --为该用户赋予权限 grant connect , Resource to ...
- html5学习笔记5--API Range对象(二)
Range对象之cloneRange和cloneContents 代码效果如下 首次点击“选择内容“按钮提示如下 接着会显示 最后显示 以下为整个代码 <!DOCTYPE html> &l ...
- android listview 异步加载图片并防止错位
网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 convertView 不会出现错位现象, 重用 convertVie ...