装饰者模式的定义

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

装饰者模式的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. 利用Vmware 创建Linux虚拟机的方法

    https://blog.csdn.net/qq_34929457/article/details/52663265 使用VMware新建一个Linux系统虚拟机 原创 2016年09月25日 17: ...

  2. 具有相同名称 的类/接口已在使用。请使用类定制设置来解决此冲突。java调用第三方的webservice应用实例

    WSDLToJava Error: http://10.96.84.124:81/BTRPWebServiceForSMB/OnSMBOrderService.svc?xsd=xsd0 [0,0]: ...

  3. CMD批处理循环,太强大了(转)

    终极dos批处理循环命令详解格式:FOR [参数] %%变量名 IN (相关文件或命令)   DO 执行的命令 作用:对一个或一组文件,字符串或命令结果中的每一个对象执行特定命令,达到我们想要的结果. ...

  4. 发现一个“佛系记账本”

    因为这是一款微信小程序,张小龙大力推崇的"用完即走"完美地适合记账应用. 不用下载.不用安装.不用注册.不用各种授权,只要从微信进入,就能记账,账本只与微信关联. 换手机.换PAD ...

  5. ubuntu下安装配置apache2与php

    1:安装apache2 sudo apt install apache2 2:修改端口号 sudo vi /etc/apache2/ports.conf 3:修改跟目录 在 /etc/apache2/ ...

  6. Python对List中的元素排序

    首先定义一个compare函数: def compare(sf1, sf2): if (sf1.value > sf2.value): return -1; elif (sf1.value == ...

  7. 【Linux】使用Google Authenticator 实现ssh登录双因素认证

    一般来说,使用ssh远程登录服务器,只需要输入账号和密码,显然这种方式不是很安全.为了安全着想,可以使用GoogleAuthenticator(谷歌身份验证器),以便在账号和密码之间再增加一个验证码, ...

  8. bootstrap table 的简单Demo

    暂时够用,不够用再补充 T_T script: <link rel="stylesheet" href="lib/bootstrap.min.css"&g ...

  9. elasticsearch外网访问设置

    默认情况下安装elasticsearch之后是无法进行外网访问的,可以通过设置来完成这一目的 1.更改配置文件 [***@elk01 ~]$ vim elk/config/elasticsearch. ...

  10. Android 隐藏系统状态栏

    通常的做法是这样的: private static boolean isStatusbarVisible(Activity activity) { int uiOptions = activity.g ...