装饰者模式的定义

动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案 

装饰者模式的UML类图

一般来说装饰者模式有下面几个参与者:

  • Component:装饰者和被装饰者共同的父类,是一个接口或者抽象类,用来定义基本行为
  • ConcreteComponent:定义具体对象,即被装饰者
  • Decorator:抽象装饰者,继承自Component,从外类来扩展ConcreteComponent。对于ConcreteComponent来说,不需要知道Decorator的存在,Decorator是一个接口或抽象类
  • ConcreteDecorator:具体装饰者,用于扩展ConcreteComponent

注:装饰者和被装饰者对象有相同的超类型,因为装饰者和被装饰者必须是一样的类型,这里利用继承是为了达到类型匹配,而不是利用继承获得行为。

利用继承设计子类,只能在编译时静态决定,并且所有子类都会继承相同的行为;利用组合的做法扩展对象,就可以在运行时动态的进行扩展。装饰者模式遵循开放-关闭原则:类应该对扩展开放,对修改关闭。利用装饰者,我们可以实现新的装饰者增加新的行为而不用修改现有代码,而如果单纯依赖继承,每当需要新行为时,还得修改现有的代码。

example:

/**
* @author yaoshw
*/
public class TestMyIdea {
public static void main(String[] args) { //不添加任何调料的饮料A
Beverage beverage = new APart();
System.out.println("Apart:" + beverage.getDescription() + "," + beverage.cost()); //添加摩卡调料的饮料B
Beverage beverage1 = new Mocha(new BPart());
System.out.println("Bpart:" + beverage1.getDescription() + "," + beverage1.cost()); //添加双份摩卡的饮料C Beverage beverage2 = new Mocha(new Mocha(new CPart()));
System.out.println("Cpart:" + beverage2.getDescription() + "," + beverage2.cost()); //添加一份摩卡、一份豆浆的饮料D Beverage beverage3 = new Soy(new Mocha(new DPart()));
System.out.println("Dpart:" + beverage3.getDescription() + "," + beverage3.cost()); }
} /**
* 抽象类,相当于Component:cost方法和getDescription方法
*/
abstract class Beverage { String description = "UnKnownBeverage"; public String getDescription() {
return description;
} public abstract double cost();
} abstract class CondimentDerector extends Beverage {
@Override
public abstract String getDescription();
} /**
* 具体装饰者:摩卡
*/
class Mocha extends CondimentDerector { /**
* 保留基类的引用,以便于组合装饰者行为
*/
Beverage beverage; public Mocha(Beverage beverage) {
this.beverage = beverage;
} @Override
public double cost() {
return beverage.cost() + 2;
} @Override
public String getDescription() {
return beverage.getDescription() + ",monka";
}
} /**
* 具体装饰者:豆浆
*/
class Soy extends CondimentDerector { Beverage beverage; public Soy(Beverage beverage) {
this.beverage = beverage;
} @Override
public double cost() {
return beverage.cost() + 3;
} @Override
public String getDescription() {
return beverage.getDescription() + "soy";
}
} /**
* 调料A
*/
class APart extends Beverage { public APart() {
description = "Apart";
} @Override
public double cost() {
return 19.5;
}
} /**
* 调料B
*/
class BPart extends Beverage { public BPart() {
description = "Bpart";
} @Override
public double cost() {
return 20.5;
}
} /**
* 调料C
*/
class CPart extends Beverage { public CPart() {
description = "Cpart";
} @Override
public double cost() {
return 21.5;
}
} /**
* 调料D
*/
class DPart extends Beverage { public DPart() {
description = "Dpart";
} @Override
public double cost() {
return 22.5;
}
}

Java设计模式系列之装饰者模式的更多相关文章

  1. JAVA设计模式之【装饰者模式】

    JAVA设计模式之[装饰者模式] 装饰模式 对新房进行装修并没有改变房屋的本质,但它可以让房子变得更漂亮.更温馨.更实用. 在软件设计中,对已有对象(新房)的功能进行扩展(装修). 把通用功能封装在装 ...

  2. 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...

  3. Java设计模式12:装饰器模式

    装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...

  4. JAVA设计模式初探之装饰者模式

    定义:动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活.设计初衷:通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种 ...

  5. java进阶系列之装饰器模式

    1.介绍 装饰器模式顾名思义就是装饰某个对象的,是一种结构型模式.装饰器模式允许向一个现有对象添加新的功能,同时不改变其结构,用户可以随意的扩展原有的对象.它是作为现有的类的一个包装.装饰器模式一方面 ...

  6. java设计模式-观察者模式,装饰者模式

    1.1定义 慨念:定义了对象之间的一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新. 即:主题和观察者定义了一对多的关系,观察者依赖于主题,只要主题发生变化,观察者就 ...

  7. Java设计模式系列之动态代理模式(转载)

    代理设计模式 定义:为其他对象提供一种代理以控制对这个对象的访问. 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念. 代理模式示例代码 public interface Sub ...

  8. Java设计模式系列之责任链模式

    责任链模式 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求.发出这个请求的客户端并不知道 ...

  9. Java设计模式系列3--抽象工厂模式(Abstract Factory Method)

    2014-02-26 10:55:47 声明:本文不仅是本人自己的成果,有些东西取自网上各位大神的思想,虽不能一一列出,但在此一并感谢! 工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果 ...

随机推荐

  1. jPlayer获取播放时间

    关于jPlayer的用法,可以参考:jPlayer 2.6.0开发者手册 http://www.jplayer.cn/developer-guide.html 视频播放例子: //视频播放 var v ...

  2. ceph:如何处理rados --striper上传失败的对象

    如何处理使用rados --striper上传失败的对象? `Remove striped objects from a ceph pool without using the striper lib ...

  3. java利用Tesseract 识别身份证号码

    安装Tesseract http://blog.csdn.net/hiredme/article/details/50894814 http://blog.csdn.net/yoara/article ...

  4. Elasticsearch集群优化

    版本配置: ES版本:6.2.4 OS内存64G. 一.参数配置: ES jvm内存31G. vi /etc/sysctl.conf vm.swappiness = 1 elasticsearch.y ...

  5. SSE图像算法优化系列八:自然饱和度(Vibrance)算法的模拟实现及其SSE优化(附源码,可作为SSE图像入门,Vibrance算法也可用于简单的肤色调整)。

    Vibrance这个单词搜索翻译一般振动,抖动或者是响亮.活力,但是官方的词汇里还从来未出现过自然饱和度这个词,也不知道当时的Adobe中文翻译人员怎么会这样处理.但是我们看看PS对这个功能的解释: ...

  6. Webhook 实践 —— 自动部署

    https://segmentfault.com/a/1190000007892407 安装nodejs 安装nodejs建议直接下载二进制包,把官网上的64位二进制版本下载地址复制下来,执行 wge ...

  7. Deep Learning.ai学习笔记_第二门课_改善深层神经网络:超参数调试、正则化以及优化

    目录 第一周(深度学习的实践层面) 第二周(优化算法) 第三周(超参数调试.Batch正则化和程序框架) 目标: 如何有效运作神经网络,内容涉及超参数调优,如何构建数据,以及如何确保优化算法快速运行, ...

  8. go微服务框架go-micro深度学习(五) stream 调用过程详解

        上一篇写了一下rpc调用过程的实现方式,简单来说就是服务端把实现了接口的结构体对象进行反射,抽取方法,签名,保存,客户端调用的时候go-micro封请求数据,服务端接收到请求时,找到需要调用调 ...

  9. RabbitMQ五种消息队列学习(三)–Work模式

    由于在实际应用中,简单队列模型无法解决很多实际问题,而且生产者和消费者是一对一的关系.模型较为单一.故引入Work模式. 结构图 一个生产者.多个消费者. 一个消息只能被一个消费者获取. 测试实现:  ...

  10. Atitit 如何在水泥森林打猎 找到合适的公司

    Atitit 如何在水泥森林打猎  找到合适的公司 1. 我们工作的本质就是打猎,万年前在草原森林里面打猎,现在在水泥森林里面打猎 2 1.1. 我们的本质职位只有一个,那就是猎人 2 1.2. 所有 ...