装饰者模式的定义

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

装饰者模式的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. Linux学习-实验楼(1)

    1.Shell:命令解释器 2.Linux技能树 3.X11:X窗口系统,其本身只是工具包及架构协议,Xorg是x架构规范的一个实现体,是实现了x协议规范的一个提供图形界面的服务器 4.终端本质上是对 ...

  2. springboot邮件发送与接收读取

    发送邮件 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>sp ...

  3. 转: ffmpeg循环推流方法

    from:  https://blog.csdn.net/weiyuefei/article/details/64125208 ffmpeg循环推流方法 You should be able to u ...

  4. 树莓派raspberry pi配置无线路由器AP

    raspi-config进入系统配置面板 进行 Expand Filesystem  扩展文件系统否则备份系统的时候备份文件会急速膨胀. (1)配置网络环境nano /etc/network/inte ...

  5. Web Workers 简介

    web worker 介绍:https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API/Using_web_workers web ...

  6. PL/SQL学习笔记之包

    一:包 包是由一组相关的函数,过程,变量,游标等PL/SQL程序设计元素的组合而成的一个PL/SQL程序单元,相当于Java中的类. 包的主要作用是封装:把相同或相似的东西归类,方便维护和管理,提高开 ...

  7. 内核中的锁机制--RCU

    一. 引言 众所周知,为了保护共享数据,需要一些同步机制,如自旋锁(spinlock),读写锁(rwlock),它们使用起来非常简单,而且是一种很有效的同步机制,在UNIX系统和Linux系统中得到了 ...

  8. 关于VC预定义常量_WIN32,WIN32,_WIN64

    VC2012 下写 Windows 程序时,有时需要判断编译环境.在之前的文章<判断程序是否运行在 Windows x64 系统下.>里说过如何在运行期间判断系统环境,但在编译时如何判断? ...

  9. What’s new for Spark SQL in Apache Spark 1.3(中英双语)

    文章标题 What’s new for Spark SQL in Apache Spark 1.3 作者介绍 Michael Armbrust 文章正文 The Apache Spark 1.3 re ...

  10. MySQL查询库和表占用的硬盘空间大小

    在mysql中有一个默认的数据表information_schema,information_schema这张数据表保存了MySQL服务器所有数据库的信息.如数据库名,数据库的表,表栏的数据类型与访问 ...