装饰者模式的定义

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

装饰者模式的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. poj3009 Curling 2.0(很好的题 DFS)

    https://vjudge.net/problem/POJ-3009 做完这道题,感觉自己对dfs的理解应该又深刻了. 1.一般来说最小步数都用bfs求,但是这题因为状态记录很麻烦,所以可以用dfs ...

  2. Win10注册表无法保存对权限所作的更改拒绝访问

    在对系统的安全控制得越来越多的情况下,要对注册表的关键数据进行修改是件挺麻烦的事,时不时会弹出无法保存对xxxxxx权限所作的更改,拒绝访问,操作产生错误,操作出现错误的提示,这时怎么办呢?这里就最近 ...

  3. Spark(四十四):使用Java调用spark-submit.sh(支持 --deploy-mode client和cluster两种方式)并获取applicationId

    之前也介绍过使用yarn api来submit spark任务,通过提交接口返回applicationId的用法,具体参考<Spark2.3(四十):如何使用java通过yarn api调度sp ...

  4. virltualbox 升级之后 苹果虚拟机报The installed support driver doesn't match the version of the user解决方案

    1.反安装virtualbox后,不要重启 2.删除virtualbox的安装目录 3.进入%userprofile% 目录 (比如: C:\users\me) 删除 .VirtualBox Virt ...

  5. git中提示 please tell me who you are

    提示也就是需要你登录一下,确认你的身份,但是不要按照其提示输入,先输入命令git config user.name “username”,换行输入git config user.email “emai ...

  6. Centos7中在线/离线安装DockerCE最新版

    Docker在Centos7在线/离线安装 一.在线安装 1.检查系统是否支持,因为Docker 要求 CentOS 系统的内核版本高于 3.10 uname -r 2.确保 yum 包更新到最新 y ...

  7. ECMAScript各版本简介及特性

    术语 ECMAScript Sun(现在的Oracle)公司持有着“Java”和“JavaScript”的商标.这就让微软不得不把自己的JavaScript方言称之为“JScript”.然后,在这门语 ...

  8. 关于docker 意外停止,重新快速启动措施

    1. 我们要重启这个镜像,需要知道这个镜像ID,类似这个: 7079ff99e10ac326726a364348853c0e508cad8ce00ae970f3c800f172a40252 那么你可以 ...

  9. 【Vegas原创】MAC下,idea手动maven jar包的方法

    1,到自己的项目目录下 Vegass-MacBook-Air:gms-boyol Vegas$ pwd/Users/Vegas/SynologyDrive/Coding/workspace/gms-b ...

  10. Android recovery支持adb shell

    Android recovery支持adb shell 近期开发过程注意到recovery不支持adb shell.为了便于调试方便,决定添加此功能. 刚開始我们採用的是user版本号系统,进入rec ...