优秀程序员必备技能:设计模式之——装饰者模式

设计模式(八)装饰器模式Decorator(结构型) 设计模式(八)装饰器模式Decorator(结构型) 1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性。如果已经存在的一个类缺少某些方法,或者须要给方法添加更多的功能(魅力),你也许会仅仅继承这个类来产生一个新类—这建立在额外的代码上。 通过继承一个现有类可以使得子类在拥有自身方法的同时........................... 阅读详情

基本介绍

相信通过名称大家可以大致猜出“装饰者模式”的含义,它的核心思想就是通过一些“装饰品(类)”对原有的基础类进行包装,从而增强或者是完成某些特定的功能。

“装饰者模式”可以动态地将新功能附加到对象上。并且在对象的扩展方面,使用该模式要比单纯的通过继承更加有弹性。

核心设计UML类图:

在这里插入图片描述

通过上面的UML类图,可以得知装饰者模式大致可以分为四个角色:

Component(抽象组件): 可以是一个抽象类或者接口,是要被包装类的顶级类。

ConcreteComponent(具体组件): Component的子类,是具体被包装的类。

注:有的时候会存在很多ConcreteComponent类,为了方便统一管理我们可以根据不同ConcreteComponent的特性在抽象出不同父类,将其放置在上图Component和ConcreteComponent之间,也就是在这两者之间设计一个缓冲层。

Decorator(装饰者): 该类继承或实现Component,并在类中聚合一个Component类的对象。

ConcreteDecorator(具体装饰者): Decorator的子类,是具体的装饰者类,该类的作用就是装饰ConcreteComponent类。

简单案例

通过上面的类图和文字描述相信大家对“装饰者模式”应该有了一些基本的认识,下面让我们通过一个小案例来加深对该设计模式的理解。

案例:有一个饮品店,该店有不同口味的饮品和不同种类的配料。现在需要一个下单系统,要求该系统可以计算出客户通过自由搭配而得的饮品价格。

饮料 => Component(抽象组件)

public abstract class Drink {

  // 描述
  private String describe;

  // 价格
  private double price = 0.0;

  // 计算费用的抽象方法
  public abstract double cost();

  // get()和set()
}

奶茶 => ConcreteComponent(具体组件)

public class TeaWithMilk extends Drink {

  public TeaWithMilk() {
    setDescribe("奶茶");
    setPrice(6.0);
  }

  @Override
  public double cost() {
    // 当前奶茶的价格
    return getPrice();
  }
}

调味品 => Decorator(装饰者)

public class Seasoning extends Drink {

  // 聚合一个Drink对象,也就是被装饰的对象。
  private Drink drink;

  // 构造
  public Seasoning(Drink drink) {
    this.drink = drink;
  }

  @Override
  public double cost() {
    // 当前调味品的价格加上被装饰对象的价格。
    return getPrice() + drink.cost();
  }

  /**
   * 重写getDescribe方法,方便输出打印
   */
  @Override
  public String getDescribe() {
    return super.getDescribe() + " " + getPrice() + " + " + drink.getDescribe();
  }
}

ConcreteDecorator(具体装饰者)

/**
 * 珍珠
 */
public class Pearl extends Seasoning {

  // 构造
  public Pearl(Drink drink) {
    super(drink);
    setDescribe("珍珠");
    setPrice(2.5);
  }
}

/**
 * 燕麦
 */
public class Oats extends Seasoning {

  // 构造方法
  public Oats(Drink drink) {
    super(drink);
    setDescribe("燕麦");
    setPrice(1.0);
  }
}

客户端测试类

public class Client {

  // 订单:一杯奶茶 + 一份燕麦 + 一份珍珠
  public static void main(String[] args) {
    // 一杯奶茶
    Drink drink = new TeaWithMilk();
    System.out.println("需支付:");
    System.out.println(drink.getDescribe() + drink.cost());

    // 加一份燕麦
    drink = new Oats(drink);
    System.out.println("加一份燕麦需支付:");
    System.out.println(drink.getDescribe() + " 总共:" + drink.cost());

    drink = new Pearl(drink);
    System.out.println("再加一份珍珠需支付:");
    System.out.println(drink.getDescribe() + " 总共:" + drink.cost());
  }
}

执行结果:

在这里插入图片描述

以上就是该案例的所有代码,可能一开始看这个代码的时候不是特别理解。不要慌,容我给大家稍加讲解,相信各位就能一目了然,明白其中的奥秘。

其实该案例运用了递归算法的思想,我们可以拆解一下。

第一步:客户下单,要了一份奶茶。
第二步:客户在奶茶的基础上,点了一个燕麦。此时我们需要装饰一下第一步中的奶茶(将其视为一个整体),从而得到一个加了燕麦的奶茶。
第三步:客户在加了燕麦的奶茶基础上,点了一个珍珠。此时我们需要装饰的就是第二步中加了燕麦的奶茶了(将其视为一个整体)。自此整个订单完成,得到一个加了燕麦和珍珠的奶茶(装饰完成)。

示例图:
在这里插入图片描述

这样解释是不是就清楚地明白其中的奥秘了。

总结

1、使用装饰者模式可以更加灵活的对程序进行扩展,可随着业务的需要动态的新增功能,也可在不需要时进行撤回,并且通过不同的装饰者和被装饰者可以衍生出不同的组合。

2、使用装饰者模式对程序进行扩展是符合ocp原则的。

3、使用装饰者模式也会增加代码的复杂性,并且当使用过度时会衍生出过多小的类,从而增加系统的维护成本。

任何设计模式都是有其优点和缺点的,我们要做到在合适的场景合理的使用设计模式。

今天的分享就到这里了,如果感觉“菜鸟”写的文章还不错,记得点赞加关注呦!你们的支持就是我坚持下去的动力。文章哪里写的有问题的也希望大家可以指出,我会虚心受教。
在这里插入图片描述

设计模式(六)桥连模式Bridge(结构型) 设计模式(六)桥连模式Bridge(结构型) 1. 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度? 例子1:设想如果要绘制矩形、圆形、椭圆、正方形,我们至少需要4个形状类,但是如果绘制的图形需要具有不同的颜色,如红色、绿色、............... 阅读详情

相关推荐

设计模式(七)组合模式Composite(结构型)

设计模式(七)组合模式Composite(结构型) 1. 概述 在数据结构里面,树结构是很重要,我们可以把树的结构应用到设计模式里面。 例子1:就是多级树形菜单。 例子2:文件和文件夹目录 2.问题 我们可以使用简单的对象组合成复杂的对象,而这个复杂对象有可以组合成更大的对象。我们可以把简单这些对象定义成类,然后定义一些容器类来存储这些简单对象。客户端代码必须区别对...

黄规速博客:学如逆水行舟,不进则退 6万+

结构型模式----装饰模式

学习设计模式有一段时间了,一直没有总结,今天开始慢慢的总结。首先介绍一下装饰模式。 作用: 装饰模式的功能就是动态的添加一些职能,同时不改变其结构。一般我们在扩展一个子类的时候经常使用继承方式实现,但是随着扩展功能的增多,如果不想在增加很多子类的情况下扩展类,就需要将具体的功能职责划分,同时继承装饰模式。 Component:定义一...

胡振涛 230

Kubernetes CRD 系列(一):CRD 介绍

CR(Custom Resource)其实就是在 Kubernetes 中定义一个自己的资源类型,是一个具体的 “自定义 API 资源” 实例,为了能够让 Kubernetes 认识这个 CR,就需要让 Kubernetes 明白这个 CR 的宏观定义是什么,也就是需要创建所谓的 CRD(Custom Resource Definition)来表述。 可能这么说并不是太直观,换个方式表达一下,我们想要创建一个 Pod 的时候,那么会编写一个 YAML 配置,然后前两行一般会这么写: [root@l

会哭的雨@的博客 7921

java-IO流(5)-IO流中的设计模式(装饰器模式和适配器模式)的介绍

1装饰器模式 定义:装饰模式是在不必改变原类文件和不使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。 2配适器模式

车车的博客 1518

[VisionPro] CogPMAlignTool 工具详解

[VisionPro] [CogPMAlignTool] [模板匹配]

weixin_43163656的博客 1万+

OAI骨关节炎数据集申请与DICOM下载全流程避坑指南

医学影像分析中,DICOM格式是存储与交换CT、MRI等数据的通用标准,其元数据Tag承载着像素间距、层厚等关键物理信息,直接影响定量分析的准确性。在骨关节炎研究领域,OAI数据集因样本量大、随访时间长而成为高价值资源,但获取需通过NDA协议申请,并借助nda-tools命令行工具完成TB级影像的批量下载与断点续传。这一流程涉及浏览器环境配置、DICOM格式转换及Python预处理等工程环节,任一细节疏漏都可能导致数据读取异常或分析偏差。掌握从申请到落地的完整链路,能显著提升医学影像AI研究的效率与可复现性

weixin_30843121的博客 276

【源码分析设计模式 5】Java I/O系统中的装饰器模式

一、基本介绍 动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。 二、装饰器模式的结构 1、Component,抽象构件 Component是一个接口或者抽象类,是定义我们最核心的对象,也可以说是最原始的对象,比如街边小吃; 2、ConcreteComponent,具体构件,或者基础构件 ConcreteComponent是最核心、最原始、最基本的接口或抽象类Component的实现,可以单独用,也可将其进行装饰,比如街边小吃最有名的手抓饼; 3、Decorat

学Java,找哪吒 9082

保姆级教程:手把手教你为裕泰微YT8521 PHY芯片编写Linux设备树(DTS)节点与驱动

本文提供了一份详细的保姆级教程,手把手教你为裕泰微YT8521 PHY芯片编写Linux设备树(DTS)节点与驱动。从基础配置到RGMII接口的特殊设置,再到驱动开发的关键步骤和调试技巧,帮助开发者快速掌握PHY芯片的移植与开发。

weixin_33734785的博客 333

学习、探究Java设计模式——装饰者模式

定义装饰者模式:在不改变原类文件以及不使用继承的情况下,动态地将责任附加到对象上,从而实现动态拓展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。设计原则要使用装饰者模式,需要满足以下设计原则: 1、多用组合,少用继承 2、开放-关闭原则:类应该对拓展开放,对修改关闭UML类图我们先来看看装饰者模式的类图,再来详细讲述: 由上自下: 1、Component是基类。通常是

蓝天白云梦的csdn博客 1万+

QGIS-空间分析-核密度分析

本文在QGIS软件中使用核密度估计法分析全球历年的地震数据,旨在分析出地震频发且严重的区域,为地震防控提供参考依据。全球历年地震数据来源于网络,仅用于技术学习探索。通过核密度分析,可以观察到南美、美国西部海岸线和太平洋北部区域在全球地震分布状态中是最为集中和强烈的。

imxiezy的博客 2467

影楼精修-肤色统一算法解析

本文介绍了影楼精修中肤色统一算法的实现方案,并以像素蛋糕软件为例进行详细分析。肤色统一旨在通过调整人像照片中皮肤区域的颜色,使其看起来更加均匀一致。像素蛋糕软件提供了AI肤色统一和传统肤色统一两种功能,分别适用于不同需求。传统肤色统一算法通过皮肤分割、人脸检测、亮度统一和颜色统一等步骤,实现了对皮肤区域的精细调整。文章还提供了亮度统一的核心代码,并对比了传统算法与AI算法的效果,指出AI算法在自然度和亮度矫正方面表现更优。整体而言,本文为影楼精修中的肤色统一提供了实用的技术参考。

Trent1985的专栏 2068

设计模式专栏——装饰器模式

概述 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。它的核心结构有四个角色:抽象构件(Component)、具体构件(ConcreteComponent)、抽象装饰器(Decorator)、具体装饰器(ConcreteDecorator) 我们通过下面的实例来演示装饰器模式的用法。我们以手抓饼

李秀才的博客 682

RK3568驱动 SPI主/从 配置

RK3568 SPI 配置指南 内核配置:启用用户空间驱动(主)和从模式协议支持。 主模式:设备树设置status="okay"、max-freq及引脚复用,子节点compatible="rockchip,spidev"。 从模式:需添加spi-slave属性,子节点命名以slave@X开头。 编译烧写:修改设备树后编译内核或全量镜像,验证/dev/spidevX.Y节点。 测试:使用spidev_test工具,主模式可环回测试,从模式需与主设备通信。 (关键:从模式强制spi-slave和命名规则,频率匹

文石_2009的博客 1146

成为一个优秀的Android开发者,需要必备哪些技术&工作技能?

前言 成为一名安卓开发者很容易,但是要成为一名成功的、突出的安卓开发者却不那么容易。这需要付出很多的努力,耐心,奉献和毅力才能做到。 我并没有什么捷径或者简单的方法来告诉你让你成为一名成功的开发者。但是如果你愿意身心投入且付出努力的话,你肯定会得到应得的成功的。 应大家的请求为成为一名更优秀的安卓开发者,这里有一些从我的经验中吸收的小巧而专业的小窍门来助你一臂之力。所以,如果你决定从事安卓开发或者已经是一名安卓开发者的话,那么你算是找对地方了。 好了,不需要再浪费口舌了,让我们开始吧。 专业的..

weixin_44339238的博客 7110

Android SystemUI——自定义状态栏和导航栏(十二)

通过前面的文章内容,我们了解了Android系统原生的状态栏StatusBar和车载系统状态栏CarStatusBar的启动流程以及视图构建流程,这里我们来简单的看一下自定义状态栏和导航栏视图的实现流程。

小旭的专栏 2012

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

高薪Java工程师必备技能分享:设计模式与框架

Java是老牌编程语言,人才需求大、应用范围广、薪资福利好。有很多人从事Java开发,但其薪资却存在较大的差异,有的人能够轻松实现月薪过万,有的人却在几千内徘徊。Java新手如何实现升职加薪?分享高薪Java工程师必备的技能之设计模式与框架。 Java设计模式 Java的设计模式大体上分为三大类: 创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。 结构型模式(7种...

xiaoxijing的博客 597

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

迈出从3K到1W的重要一步——掌握设计模式

IT职场的小菜经常有这样的疑问:         为什么一个相似的功能,大牛一会儿就搞定,然后悠闲地品着下午茶逛淘宝;而自己加班加点搞到天亮还做不完。         为什么用户提出需求变更后,大牛只需潇洒地敲敲键盘,改改配置;而自己将代码改了又改,删了又建,几乎晕厥,最后只能推翻重来。         为什么大牛写完的程序测试上线后,几乎完美运行,用户无懈可击;而自己的程序bug重重,改好

三级小野怪的专栏 4万+

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

java与模式_高薪Java工程师必备技能分享:设计模式与框架

Java是老牌编程语言,人才需求大、应用范围广、薪资福利好。有很多人从事Java开发,但其薪资却存在较大的差异,有的人能够轻松实现月薪过万,有的人却在几千内徘徊。Java新手如何实现升职加薪?千锋石家庄Java培训小编分享高薪Java工程师必备的技能之设计模式与框架。Java设计模式Java的设计模式大体上分为三大类:创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。...

weixin_39985820的博客 79

优秀软件开发大佬的技能树!

开发人员是软件项目的核心力量,他们负责将设计转化为可运行的代码,实现业务逻辑,确保系统的稳定、高效运行。

日拱一卒,玉汝于成 2248

5本最佳的Java面向对象理论和设计模式的书籍

对于Java程序员来说,掌握面向对象的设计理论和一些设计模式是必备技能。就像我在另一篇博客Java程序员应该知道的10个面向对象理论中提到的,不学理论就开始编程,就类似于学习一种语言而不学习字母表。市面上有很多有关面向对象理论的、设计模式的和最佳实践的,但只有很少的书真正值得我们阅读。这里涉及两件事情,一个是面向对象理论,一个是设计模式。前者是基础,后者是在基于基础的最佳实践。我们应该先学习面向对...

gotodiscover的博客 7804

java rowmapper 通用实现_高薪Java工程师必备技能分享:设计模式与框架

Java是老牌编程语言,人才需求大、应用范围广、薪资福利好。有很多人从事Java开发,但其薪资却存在较大的差异,有的人能够轻松实现月薪过万,有的人却在几千内徘徊。Java新手如何实现升职加薪?千锋石家庄Java培训小编分享高薪Java工程师必备的技能之设计模式与框架。Java设计模式Java的设计模式大体上分为三大类:创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。...

weixin_29208327的博客 89

Java开发工程师升职加薪必备技能:Java设计模式与框架

Java是老牌编程语言,人才需求大、应用范围广、薪资福利好。有很多人从事Java开发,但其薪资却存在较大的差异,有的人能够轻松实现月薪过万,有的人却在几千内徘徊。Java新手如何实现升职加薪?千锋重庆Java培训小编分享高薪Java工程师必备的技能之设计模式与框架。 ​ Java设计模式 Java的设计模式大体上分为三大类: 创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。 结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。 行为型

qf2019的博客 113

掌握设计模式(什么是设计模式)

IT职场的小菜经常有这样的疑问: 为什么一个相似的功能,大牛一会儿就搞定,然后悠闲地品着下午茶逛淘宝;而自己加班加点搞到天亮还做不完。 为什么用户提出需求变更后,大牛只需潇洒地敲敲键盘,改改配置;而自己将代码改了又改,删了又建,几乎晕厥,最后只能推翻重来。 为什么大牛写完的程序测试上线后,几乎完美运行,用户无懈可击;而自己的程序bug重重,改好一...

gf6699681811的博客 209

成为一个优秀的Android开发者,需要必备哪些技术&工作技能?(1)

这能够开阔你的视野,并能够显著地提升你的安卓开发技巧。下定决心每年至少学习一门新的编程语言吧。但是,请不要在仅仅一周的尝试后就跳过这门语言而放弃学习。尝试着深入这门语言并弄懂它内部的工作原理。在长远看来,我并不能完全阐明这会对你的安卓开发生涯有多大的影响。任何时刻,你被卡在需要解决的某个严重的程序问题的时候,设计模式着实能帮助你构建一个优雅的解决方案。你也需要保持和其他程序员一致的节奏,因此他们在谈论关于使用工厂模式或者装饰着模式或者外观模式的时候,你也能够立马懂得他们所指的含义。

2401_84545213的博客 346

5本最佳的Java面向对象理论和设计模式的书籍(转)

本文由 ImportNew - 唐小娟 翻译自 Javarevisited。欢迎加入Java小组。转载请参见文章末尾的要求。 对于Java程序员来说,掌握面向对象的设计理论和一些设计模式是必备技能。就像我在另一篇博客Java程序员应该知道的10个面向对象理论中 提到的,不学理论就开始编程,就类似于学习一种语言而不学习字母表。市面上有很多有关面向对象理论的、设计模式的和最佳实践的,但只...

HERO_1990的博客 659
上一篇: 一文带你学会“桥接模式”,不会你找我
下一篇: 程序员必备技能:设计模式之——组合模式
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值