设计模式 之 装饰者(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)模式
虽然目前房价依旧很高,就连我所在的成都郊区(非中心城区)的房价均价都早已破万,但却还是阻挡不了大家对新房的渴望和买房的热情.如果大家买的是清水房,那么无疑还有一项艰巨的任务在等着大家,那就是装修.对新 ...
随机推荐
- 设置与获取Cookie
自己编写的一个Cookie设置与获取函数,大家有什么感觉需要改进的地方,请告知与我,我一定虚心接受. JavaScript - Code: function setCookie(name,value, ...
- js操纵css更改加载图片大小
- Oracle数据库,查询语句、内置函数
一.数据库的查询语句: 1.查询整个表: select * from 表名 例: 2.通过条件查询某一行数据: select * from 表名 where 字段名 例: 3.某一列数据去重查询: s ...
- sublime text 开发常用插件
一.emmet插件 (HTML/CSS代码快速编写插件) 安装步骤:打开Sublime菜单栏>首选项>Package Control> 输入>Package Control: ...
- python不用加号实现加法
问题: Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -.E ...
- GitHub上新建或删除仓库Repository
一:新建仓库 在首页的New Repository,点击进入页面,输入和项目同名的仓库名就可以了.
- 项目总结笔记系列 Maven Session1
主题:Maven 参考地址: 1.http://www.yiibai.com/maven/ 2.http://www.icoolxue.com/ 目录 1.环境搭建 2.pom.xml文件解析 3.m ...
- 基础-WeakReference
一.概述 为了更好的理解WeakHashMap的原理,我们有必要先来了解一下WeakReference的作用及实现原理.Java中有一个专门的包java.lang.ref,里面定义了我们通常所说的几种 ...
- HBase集群安装过程中的问题集锦
1.HRegionServer启动不正常 在namenode上执行jps,则可看到hbase启动是否正常,进程如下: [root@master bin]# jps26341 HMaster26642 ...
- jQuery超酷下拉插件6种效果演示
原始的下拉框很丑啦, 给大家一款jQuery超酷下拉插件6种效果 效果预览 下载地址 实例代码 <div class="container"> <section ...