装饰者模式(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)模式的更多相关文章

  1. Head First 设计模式 —— 03. 装饰器 (Decorator) 模式

    思考题 有如下类设计: 如果牛奶的价钱上扬,怎么办?新增一种焦糖调料风味时,怎么办? 造成这种维护上的困难,违反了我们之前提过的哪种设计原则? P82 取出并封装变化的部分,让其他部分不收影响 多用组 ...

  2. 设计模式之装饰(Decorator)模式

    设计模式之装饰(Decorator)模式 (一)什么是装饰(Decorator)模式 装饰模式,又称为包装模式,它以对客户端透明的方式扩张对象的功能,是继承关系的替代方案之一. 装饰模式可以在不使用创 ...

  3. java设计模式03装饰者者模式

    动态地给一个对象添加一些额外的职责.就增加功能来说, Decorator模式相比生成子类更为灵活.该模式以对客 户端透明的方式扩展对象的功能. (1)在不影响其他对象的情况下,以动态.透明的方式给单个 ...

  4. 设计模式之装饰(Decorator)模式 代码详解

    /** * Created with IntelliJ IDEA. * User: HYY * Date: 13-10-27 * Time: 下午10:49 * To change this temp ...

  5. 装饰器(Decorator)模式

    public interface IDoThings { public void doSomeThing(); } public class DoThings implements IDoThings ...

  6. JS 设计模式九 -- 装饰器模式

    概念 装饰者(decorator)模式能够在不改变对象自身的基础上,动态的给某个对象添加额外的职责,不会影响原有接口的功能. 模拟传统面向对象语言的装饰者模式 //原始的飞机类 var Plane = ...

  7. 学习javascript设计模式之装饰者模式

    1.装饰者模式定义:给对象动态添加职责的方式称为装饰者(decorator)模式. js如何实现装饰者模式 通过保存原函数引用方式改写某函数 window.onload = function(){al ...

  8. C#设计模式(9)——装饰者模式(Decorator Pattern)

    一.引言 在软件开发中,我们经常想要对一类对象添加不同的功能,例如要给手机添加贴膜,手机挂件,手机外壳等,如果此时利用继承来实现的话,就需要定义无数的类,如StickerPhone(贴膜是手机类).A ...

  9. [设计模式] 9 装饰者模式 Decorator

    转:http://www.jellythink.com/archives/171#prettyPhoto 什么是装饰模式? 在GOF的<设计模式:可复用面向对象软件的基础>一书中对装饰模式 ...

  10. 设计模式的征途—10.装饰(Decorator)模式

    虽然目前房价依旧很高,就连我所在的成都郊区(非中心城区)的房价均价都早已破万,但却还是阻挡不了大家对新房的渴望和买房的热情.如果大家买的是清水房,那么无疑还有一项艰巨的任务在等着大家,那就是装修.对新 ...

随机推荐

  1. JavaScript基础插曲-练习

    Javascript基础学习 eg:利用正则表达式来去掉空格. 1:msg=' Hello ': <script type="text/javascript">     ...

  2. LeetCode - Flatten Binary Tree to Linked List

    题目: Given a binary tree, flatten it to a linked list in-place. For example, Given 1 / \ 2 5 / \ \ 3 ...

  3. C# 委托和事件(一):最简单的委托和事件

    C#的事件基于委托,所以先说委托. 一切脱离实际场景的抽象概念新手看上去就像是在扯犊子,不错,我就是个新手.所以我需要一个实际的场景. 明天刚好考试(商务英语),考试上有两个角色(class):老师( ...

  4. 15天玩转redis —— 第六篇 有序集合类型

    今天我们说一下Redis中最后一个数据类型 “有序集合类型”,回首之前学过的几个数据结构,不知道你会不会由衷感叹,开源的世界真好,写这 些代码的好心人真的要一生平安哈,不管我们想没想的到的东西,在这个 ...

  5. WCF学习笔记1--发布使用配置文件的服务

    关于WCF的入门网上资料很多,可以参考蒋金楠老师的博客http://www.cnblogs.com/artech/archive/2007/02/26/656901.html,我是从这篇博客开始学习的 ...

  6. ASP.NET中的随机密码生成

    第一种方法:用.NET中的 Sytem.Guid.NewGuid().ToString() 生成,实际上是对一个128bit数字的十六进制输出.生成的字符由0-9和a-z这几种字符组成,也可能会有“- ...

  7. EC笔记,第一部分:1.视C++为一个语言联邦

    C++可看作由以下四种次语言组合而成1.C语言    高效,内置数据类型,数组,区块,语句,指针,预处理器,没有重载.异常.模板2.类    构造,析构,封装,继承,多态,迟绑定3.模板    模板元 ...

  8. SSH服务器与Android通信(3)--Android客户端发送数据

    Android客户端向SSH服务器发送数据主要有三种情况:通过客户端删除数据.添加数据和修改数据. 1.删除数据 先看看jsp文件里面是怎样删除数据的: <td align="cent ...

  9. MySQL Workbench返回所有的记录

    使用MySQL Workbench查询数据库,当返回的记录较多时,不能显示所有的记录,因为MySQL Workbench默认只返回1000条记录. 为了显示所有的记录,可以在查询语句后面加一句: LI ...

  10. 【转】php中XML、XSLT的结合运用

    原文:http://blog.csdn.net/bjbs_270/article/details/140253   下面我要讲的是一个简单的从数据库中抽取数据,生成XML文档,使用XSLT转换成HTM ...