故事:穿什么有这么重要?

定义:

装饰模式:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。

但是纯粹的装饰模式很难找到,大多数的装饰模式的实现都是“半透明”的,而不是完全透明的。换言之,允许装饰模式改变接口,增加新的方法。半透明的装饰模式是介于装饰模式和适配器模式之间的。适配器模式的用意是改变所考虑的类的接口,也可以通过改写一个或几个方法,或增加新的方法来增强或改变所考虑的类的功能。

大多数的装饰模式实际上是半透明的装饰模式,这样的装饰模式也称做半装饰、半适配器模式。

Component 是定义一个对象接口,可以给这些对象动态的添加职责。ConcreteComponent是定义一个具体的对象,也可以给这个对象添加一些职责。Decorator,装饰抽象类,继承了component,从外类来扩展component类的功能,但对于Component来说,是无需知道Decorator的存在的。至于ConcreteDecorator就是具体的装饰对象,起到给Component添加职责的功能。

针对的问题:

动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。不改变接口的前提下,增强所考虑的类的性能。

何时使用:

1)需要扩展一个类的功能,或给一个类增加附加责任。

2)需要动态的给一个对象增加功能,这些功能可以再动态地撤销。

3)需要增加一些基本功能的排列组合而产生的非常大量的功能,从而使继承变得    不现实。

实例:

咖啡是一种饮料,咖啡的本质是咖啡豆+水磨出来的。咖啡店现在要卖各种口味的咖啡,如果不使用装饰模式,那么在销售系统中,各种不一样的咖啡都要产生一个类,如果有4中咖啡豆,5种口味,那么将要产生至少20个类(不包括混合口味),非常麻烦。使用了装饰模式,只需要11个类即可生产任意口味咖啡(包括混合口味)。

Beverage饮料接口

/** * 饮料接口 * @author Administrator * */
public interface Beverage {  //返回商品描述  public String getDescription();  //返回价格  public double getPrice();
}

  

CoffeeBean1——具体被装饰的对象类1

public class CoffeeBean1 implements Beverage {  private String description = "选了第一种咖啡豆";  @Override  public String getDescription() {  return description;  }  @Override  public double getPrice() {  return 50;  }  }

  CoffeeBean2——具体被装饰的对象类2

public class CoffeeBean2 implements Beverage {  private String description = "第二种咖啡豆!";  @Override  public String getDescription() {  return description;  }  @Override  public double getPrice() {  return 100;  }  }

  Decorator——装饰类

public class Decorator implements Beverage {  private String description = "我只是装饰器,不知道具体的描述";  @Override  public String getDescription() {  return description;  }  @Override  public double getPrice() {  return 0;       //价格由子类来决定  }  }

  

Milk——具体装饰类,给咖啡加入牛奶

public class Milk extends Decorator{  private String description = "加了牛奶!";  private Beverage beverage = null;  public Milk(Beverage beverage){  this.beverage = beverage;  }  public String getDescription(){  return beverage.getDescription()+"\n"+description;  }  public double getPrice(){  return beverage.getPrice()+20;  //20表示牛奶的价格  }
}

  

Mocha——给咖啡加入摩卡

public class Mocha extends Decorator {  private String description = "加了摩卡!";  private Beverage beverage = null;  public Mocha(Beverage beverage){  this.beverage = beverage;  }  public String getDescription(){  return beverage.getDescription()+"\n"+description;  }  public double getPrice(){  return beverage.getPrice()+49;  //30表示摩卡的价格  }
}

  

Soy——给咖啡加入豆浆

public class Soy extends Decorator {  private String description = "加了豆浆!";  private Beverage beverage = null;  public Soy(Beverage beverage){  this.beverage = beverage;  }  public String getDescription(){  return beverage.getDescription()+"\n"+description;  }  public double getPrice(){  return beverage.getPrice()+30;  //30表示豆浆的价格  }
}

  测试类:

public class Test {  public static void main(String[] args) {  Beverage beverage = new CoffeeBean1();  //选择了第一种咖啡豆磨制的咖啡  beverage = new Mocha(beverage);     //为咖啡加了摩卡  beverage = new Milk(beverage);  System.out.println(beverage.getDescription()+"\n加了摩卡和牛奶的咖啡价格:"+beverage.getPrice());  }
}

  

测试结果:

装饰模式和适配器模式的关系:

  装饰模式和适配器模式都是“包装模式(Wrapper Pattern)”,它们都是通过封装其他对象达到设计的目的的,但是它们的形态有很大区别。

  理想的装饰模式在对被装饰对象进行功能增强的同时,要求具体构件角色、装饰角色的接口与抽象构件角色的接口完全一致。而适配器模式则不然,一般而言,适配器模式并不要求对源对象的功能进行增强,但是会改变源对象的接口,以便和目标接口相符合。

  装饰模式有透明和半透明两种,这两种的区别就在于装饰角色的接口与抽象构件角色的接口是否完全一致。透明的装饰模式也就是理想的装饰模式,要求具体构件角色、装饰角色的接口与抽象构件角色的接口完全一致。相反,如果装饰角色的接口与抽象构件角色接口不一致,也就是说装饰角色的接口比抽象构件角色的接口宽的话,装饰角色实际上已经成了一个适配器角色,这种装饰模式也是可以接受的,称为“半透明”的装饰模式,如下图所示。

在适配器模式里面,适配器类的接口通常会与目标类的接口重叠,但往往并不完全相同。换言之,适配器类的接口会比被装饰的目标类接口宽。

显然,半透明的装饰模式实际上就是处于适配器模式与装饰模式之间的灰色地带。如果将装饰模式与适配器模式合并成为一个“包装模式”的话,那么半透明的装饰模式倒可以成为这种合并后的“包装模式”的代表。

优点:

(1)装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。装饰模式允许系统动态决定“贴上”一个需要的“装饰”,或者除掉一个不需要的“装饰”。继承关系则不同,继承关系是静态的,它在系统运行前就决定了。

(2)通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

缺点:

使用装饰模式会产生比使用继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去都很相像。

转载于:https://www.cnblogs.com/zhanghu52030/p/7912345.html

设计模式---装饰模式相关推荐

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

    设计模式--装饰模式 "装饰模式(Decorator)"又名"包装模式(Wrapper)",通常用来灵活地扩充对象的功能. 在此之前我们可以通过类的继承来扩充父 ...

  2. 大话设计模式-装饰模式(大鸟和小菜Java版)

    装饰模式:装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象.(百度百科) 这个模式让后期的修改变得极为简单,真的就高内 ...

  3. 大话设计模式—装饰模式

    装饰模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构.这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装原 ...

  4. 设计模式--装饰模式

    目录 什么是装饰模式? 应用代码示例 装饰模式模板 jdk中的装饰模式 为什么装饰器类不能直接实现Component父类? 什么是装饰模式? 以生活中的场景来举例,一个蛋糕胚,给它涂上奶油就变成了奶油 ...

  5. C++设计模式-装饰模式

    目录 基本概念 代码和实例 基本概念 装饰模式是为已有功能动态地添加更多功能的一种方式. 当系统需要新功能的时候,是向旧系统的类中添加新代码.这些新代码通常装饰了原有类的核心职责或主要行为. 装饰模式 ...

  6. 李建忠设计模式——装饰模式

    1."单一职责"模式 在软件组件的设计中,如果责任划分不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任. 典型模式 Deco ...

  7. C++设计模式——装饰模式(高屋建瓴)

    原网址:https://blog.csdn.net/CoderAldrich/article/details/83115394 重点在于 ConcreteDecoratorA(Component *d ...

  8. java设计模式——装饰模式

    装饰模式也称为包装模式.结构型设计模式之一,其使用一种对客户端透明的方式动态的扩展对象的功能,同时它也是继承关系的一种替代方案之一. 装饰模式可以动态的给一个对象添加一些额外的职责.就增加功能功能来说 ...

  9. 设计模式——装饰模式详解

    0. 前言   写在最前面,本人的设计模式类博文,建议先看博文前半部分的理论介绍,再看后半部分的实例分析,最后再返回来复习一遍理论介绍,这时候你就会发现我在重点处标红的用心,对于帮助你理解设计模式有奇 ...

  10. 设计模式 | 装饰模式

    1 | 装饰模式的概述 我们在了解装饰模式之前,先回顾下生活中的几个常见现象,举例如下: 新房的装修,房屋装修并没有改变房屋居住的本质,但可以让房屋变得更漂亮,更温馨,更实用,更满足居家需求. 相片的 ...

最新文章

  1. rancher 外置 mysql_rancher使用外部数据库无法正常使用
  2. Android10.0 Binder通信原理(三)-ServiceManager篇
  3. 第8部分 管理磁盘存储
  4. mongodb 启动_精心总结--mongodb分片集群启动与关闭
  5. 发布nuget包的正确姿势---cicd自动打包发布
  6. RigUp 数据库暴露7.6万份美国能源行业文件
  7. 零基础学python用哪本书好-零基础自学python3 好用的入门书籍推荐
  8. Gstreamer之重置PTS与DTS流程(二十)
  9. 聚类的基本概念-聚类与分类的区别
  10. 电力载波通信模块JST-HPLC-N-C在物联网通信领域的应用
  11. PyTorch以及VGG模型
  12. 短视频app搭建的技术难点是什么?
  13. 一文看懂:Android-Q版本在安全方面进行了哪些系统性改进
  14. 终端运行npm install @tinymce/tinymce-vue -S报错的解决办法
  15. 2015年ps计算机试题,2015年3月全国计算机一级考试ps模拟试题及答案(二).doc
  16. MySQL高可用方案之PXC架构
  17. 小型水库雨水情测报及大坝安全监测建设介绍
  18. ff新推荐弹窗怎么彻底删除---解决方案
  19. MatLab入门手册
  20. 订单波次出库详解:流程、系统与设备

热门文章

  1. 1035 插入与归并 (25 分)(c++)
  2. LVS(13)——DR模型准备工作及ip地址冲突问题
  3. 张朝阳:我什么都有,但我就是很痛苦
  4. 使用 ApplicationLoader 上传应用到 Appstore
  5. 关于使用spring管理hibernate,能够管理事务,却不执行除查询外的增删改操作,不能让数据库数据改变的原因
  6. J钓鱼 (vector + queue)
  7. VS Code运行Python程序
  8. ×××××sales_data通过类型转换形成的临时对象不能转换成sales_data (非常量引用)
  9. [C++] this指针
  10. C 语言 普通基本数据类型 以及 其储存形式