装饰者模式(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. Emit学习(2) - IL - 常用指令介绍

    学习Emit必不可少的, 会使用到IL中间代码. 初见IL代码, 让我有一种汇编的感觉, 让我想起了, 大学时, 学习8051的汇编语言. 多的就不扯了, 直接进入正题, OpCodes指令集是不是有 ...

  2. 交换排序---冒泡排序算法(Javascript版)

    比较相邻的元素.如果第一个比第二个大,就交换他们两个.对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数.针对所有的元素重复以上的步骤,除了最后一个.持续 ...

  3. WinForm 简单蒙版实现控件遮盖

    在Web上面要实现一个遮罩层或者说是蒙版吧,有了DIV那不算什么难事,只要给div定好位置和大小,把颜色的Alpha值设一下就有透明的效果.不过在Winform中实现起来就没那么简单了事.尝试过用一个 ...

  4. iOS阶段学习第31天笔记(UINavigationBar介绍)

    iOS学习(UI)知识点整理 一.UINavigationBar 的介绍 1)概念:UINavigationBar 是用于定义导航栏按钮的一个类对象 2)在使用UINavigationBar之前必须先 ...

  5. 自己动手,让Entity Framework Power Tools在VS2015重放光彩

    Entity Framework Power Tools是一个由EntityFramework开发小组提供的工具,它可以从现有数据库生成Fluent款式的Code First代码. VS Galler ...

  6. jquery更改加载图片大小

    <script type="text/javascript"> $("img").css("width","80%&q ...

  7. spring 使用redis集群配置

    上面两篇介绍了redis集群的配置合一些基本的概念,所以接下来当然是要在项目中使用咯,redis的java支持已经做的非常好了,所以我们来试着使用这些api来进行redis的操作,首先我们需要操作re ...

  8. 2013ACM/ICPC亚洲区南京站现场赛---Poor Warehouse Keeper(贪心)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=4803 Problem Description Jenny is a warehouse keeper. ...

  9. 用java实现新浪爬虫,代码完整剖析(仅针对当前SinaSignOn有效)

    先来看我们的web.xml文件,如下 <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application ...

  10. mysql 5.6 read-committed隔离级别下并发插入唯一索引导致死锁一例

    今天,某个环境又发生了死锁,如下: *** (1) TRANSACTION:TRANSACTION 735307073, ACTIVE 0 sec insertingmysql tables in u ...