定义

能够动态的给对象增加行为职责的一种模式,灵活性远胜于继承。

主要组成

抽象组件(Component): 定义抽象行为接口。

具体组件(Concrete component): 定义具体实现行为接口的类,继承自抽象组件,也做被装饰者,用于被附加各种行为。

抽象装饰者(Decorator):持有一个Component的引用,并继承自Component,提供其一致的接口。这边继承自Component来达到类型匹配的效果,而不是为了利用继承来获取行为,行为来自装饰者与基础组件的组合关系

具体装饰者(Concrete Decorator):负责给Component组件对象添加具体的责任,继承自Decorator

UML类图

框架代码

抽象组件(Component):

public interface Component {void methodA();void methodB();
}

具体组件(Concrete component):

public class ConcreteComponent implements Component{@Overridepublic void methodA() {//...}@Overridepublic void methodB() {//...}
}

抽象装饰者(Decorator):

public abstract class Decorator implements Component{Component component;public  Decorator(Component component) {this.component = component;}
}

具体装饰者(Concrete Decorator):

public class ConcreteDecoratorA extends Decorator{public ConcreteDecoratorA(Component component) {super(component);}@Overridepublic void methodA() {component.methodA();//...装饰者扩展Component状态}@Overridepublic void methodB() {component.methodB();//...装饰者扩展Component状态}}public class ConcreteDecoratorB extends Decorator{public ConcreteDecoratorB(Component component) {super(component);}@Overridepublic void methodA() {//...}@Overridepublic void methodB() {//...}}

具体例子

以销售咖啡为例,为咖啡店设计实现饮料售价的类结构,假设存在: 咖啡种类:美式咖啡(American coffee)、英式咖啡(English coffee)、拿铁(Latte),售价分别为每杯15,16,17元。 配料种类:蒸奶(Milk)、豆浆(Soy)、摩卡(Mocha),售价为每份3,1,2元。

UML类图

代码

Beverage(对应抽象组件Component):

public interface Beverage {float cost();
}

Coffee(对应具体组件Concrete component):

美式咖啡:

public class AmericanCoffee implements Beverage{@Overridepublic float cost() {return 15;}}

英式咖啡:

public class EnglishCoffee implements Beverage{@Overridepublic float cost() {return 16;}}

拿铁:

public class Latte implements Beverage{@Overridepublic float cost() {return 17;}
}

调料(对应抽象装饰者Decorator):

public abstract class Decorator implements Beverage{Beverage beverage;public Decorator(Beverage beverage) {this.beverage = beverage;}
}

具体调料(对应具体装饰者Concrete Decorator):

蒸奶:

public class Milk extends Decorator{public Milk(Beverage beverage) {super(beverage);}@Overridepublic float cost() {return beverage.cost() + 3;}
}

豆浆:

public class Soy extends Decorator{public Soy(Beverage beverage) {super(beverage);}@Overridepublic float cost() {return beverage.cost() + 1;}
}

摩卡:

public class Mocha extends Decorator{public Mocha(Beverage beverage) {super(beverage);}@Overridepublic float cost() {return beverage.cost() + 2;}
}

客户端调用

点一杯美式咖啡加蒸奶、豆浆 , 以及一杯英式咖啡加蒸奶、双份摩卡,各自计算总价:

 //计算美式咖啡加蒸奶、豆浆的总价Beverage americanCoffee = new AmericanCoffee();float cost = new Soy(new Milk(americanCoffee)).cost();System.out.println(cost + "");//计算美式咖啡加蒸奶、双份摩卡的总价Beverage englishCoffee = new EnglishCoffee();cost = new Mocha(new Mocha(new Milk(englishCoffee))).cost();System.out.println(cost + "");

假设不使用装饰者模式

不使用装饰者模式,而是都统一采用继承的方式来解决的话,会导致类数量上呈现爆炸式增加,如下uml图所示(只列出部分),并且这还是未考虑全部添加混合调料或者多份重复调料的情况下的一种类图结构,数量明显多于上面的装饰者模式。 一旦新增加一种coffee或者新增加一种具体调料、或者修改价钱,则维护是致命的,涉及到要修改或者新增太多的类。

假设使用如下解决方法:

这种方案一旦增加一种新的调理,可能会导致所有的子类cost都需要跟着修改。并且单设增加一种产品比如"tea"是不允许添加mocha调料的,这种方案就无法避免,会引入不必要的信息。

总结

一种动态扩展的方式,比继承更加具有灵活性。

优点

  1. 比继承更灵活,动态、灵活的向对象添加删除职责,相比之下继承要求使用前静态创建类对象,类数量暴涨、复杂度增大
  2. 同一特性支持复用,比如用同一装饰者多次装饰(例如用"边框"装饰者装饰2次就可以达到"双边框"的效果)
  3. 将特性有装饰者实现,避免基础类需要维护太多的特性,导致职责过于复杂

缺点

可能产生许多小对象,对不理解该结构的人来讲,有点难以学习

应用场景

在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责,避免因为组合而需要创建大量的之类。

微信公众号

小白设计模式:装饰者模式相关推荐

  1. Python设计模式-装饰器模式

    Python设计模式-装饰器模式 代码基于3.5.2,代码如下; #coding:utf-8 #装饰器模式class Beverage():name = ""price = 0.0 ...

  2. [Head First设计模式]山西面馆中的设计模式——装饰者模式

    原文:[Head First设计模式]山西面馆中的设计模式--装饰者模式 引言 在山西面馆吃鸡蛋面的时候突然想起装饰者这个模式,觉得面馆这个场景跟书中的星巴兹咖啡的场景很像,边吃边思考装饰者模式.这里 ...

  3. 设计模式——装饰者模式

    本文是阅读 Head First 设计模式--装饰者模式的总结. 这本书的教学模式很不错,个人很喜欢,由实际的案例由浅入深,循序渐进的让你明白良好的设计是多么的优雅迷人(回头看看自己的代码,WTF!) ...

  4. 设计模式装饰者模式_装饰者模式如何拯救了我的一天

    设计模式装饰者模式 在工作中,我正在处理庞大的Java代码库,该代码库是由许多不同的开发人员在15年的时间里开发的. 并不是所有的事情都由书来完成,但是同时我通常无法重构遇到的每一个奇怪的事物. 尽管 ...

  5. 23种设计模式——装饰者模式

    文章目录 23种设计模式--装饰者模式 1.装饰者模式概述 2.装饰者模式的结构 3.装饰者模式的实现 4.装饰者模式的应用场景 23种设计模式--装饰者模式 1.装饰者模式概述 背景 有些人为了早上 ...

  6. 码农小白 设计模式篇 状态模式

    码农小白 设计模式篇 状态模式 1.状态的认识 2.面向过程思维的代码实现 小结: 3.面向对象实现 小结 4.用状态模式实现 1.状态模式的简介 2.状态模式的好处 3.状态模式的使用 4.代码实现 ...

  7. 读书笔记---Head First 设计模式--- 装饰者模式

    读书笔记-Head First 设计模式- 装饰者模式 装饰者模式(Decorator Pattern) 装饰者模式--动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. ...

  8. Go 设计模式 - 装饰器模式

    装饰模式使用对象组合的方式动态改变或增加对象行为.Go语言借助于匿名组合和非入侵式接口可以很方便实现装饰模式.使用匿名组合,在装饰器中不必显式定义转调原对象方法. 设计模式 装饰器模式 装饰器模式主要 ...

  9. 10. 设计模式-装饰者模式

    文章目录 设计模式-装饰者模式 1. 案例引出装饰者模式 2. 装饰者模式 2.1 装饰者模式定义 2.2 装饰者模式原理 2.3 装饰者模式解决星巴克咖啡订单问题 2.4 代码实现 抽象类Drink ...

  10. Spring设计模式(装饰器模式)

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

最新文章

  1. ios开发 微博图片缩放处理错误_H5响应式开发必会之Viewport(视窗)详解
  2. HTTP协议常用标准状态码含义
  3. rgb红色范围_UI设计教程分享之RGB与CMYK色彩模式对比
  4. jquery-easyui环境的搭建及测试
  5. ElasticSearch大数据分布式弹性搜索引擎使用—从0到1
  6. php不用密码登录,使用散列密码登录PHP
  7. MyBatis-Plus 乐观锁 防止超卖、逻辑删除、自动填充、Id自增
  8. JAndFix: 基于Java实现的Android实时热修复方案
  9. Apache与Nginx比较(Nginx 高并发情况常用,必须学习)
  10. linux查找文件命令 要查找包含某字符
  11. canvas技术整理
  12. 如何用python读取表_Python读取MySQL表数据的方法介绍
  13. gimp中文版教程_GIMP中文详细教程.pdf
  14. opencv c++讲解jzg mxy tyd_python看代码就行
  15. 逼疯UE设计师,不可不知的提升产品用户体验的10个测试方法
  16. 一文详解synchronized与volatile
  17. OLED显示与LCD相比的优缺点都有哪些
  18. 基于芯科Host-NCP解决方案的Zigbee 3.0 Gateway技术研究(三)-移植到ESP32平台(1)
  19. python爬虫实操|爬取nba中国官网球员数据
  20. 【自然语言处理】Word2Vec 词向量模型详解 + Python代码实战

热门文章

  1. eos java是什么框架_EOS的整体框架
  2. autojs 如何获取控件的desc_owchart教程三:如何添加成交量?
  3. 阿里云搭建流媒体服务器
  4. Linux下文件开头的feff的问题
  5. 轻量级数据交换格式JSON
  6. js获取form表单数据和form表单赋值
  7. 顶级产品经理是如何写产品需求文档(PRD)的
  8. 安全测试===sqlmap(壹)转载
  9. Hadoop入门扫盲:hadoop发行版介绍与选择
  10. Only a type can be imported解决方法