Java设计模式——装饰者模式

embedded/2024/10/21 10:20:23/

Java设计模式——装饰者模式

1.简介

'装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许用户通过在一个对象上动态地添加职责或行为来增强其功能。这种类型的设计模式属于对象结构型模式,在不需要改变一个对象的内部结构的条件下,给对象动态地增加一些额外的职责。装饰者模式相比生成子类更为灵活。

2.核心组成

装饰者模式主要包含以下四种角色:

  1. 抽象组件(Component):定义一个对象的接口,可以给这些对象动态地添加职责。
  2. 具体组件(ConcreteComponent):实现或继承抽象组件,并添加基础的行为或属性。
  3. 装饰者(Decorator):持有一个抽象组件的引用,并定义一个与抽象组件一致的接口。
  4. 具体装饰者(ConcreteDecorator):实现装饰者接口,并给具体组件对象添加额外的职责。

3.工作原理

装饰者模式的工作原理是动态地将责任附加到对象上。若要扩展一个类的功能,装饰者提供了一个比继承更有弹性的替代方案。

4.使用场景

  1. 动态地给一个对象添加功能:装饰者模式允许我们在运行时动态地给一个对象添加职责,而不是在编译时静态地定义。
  2. 扩展功能不改变接口:使用装饰者模式时,不需要修改现有类的接口,就可以在运行时动态地扩展类的功能。
  3. 透明地使用对象:装饰者模式中的装饰者对象和被装饰对象实现了相同的接口,所以客户端代码可以透明地使用它们,不需要知道它们到底是装饰者对象还是被装饰对象。

5.优缺点

优点

  1. 装饰者和被装饰对象有相同的超类,因此继承了装饰者模式中的装饰对象和被装饰对象的类型一致性的特点。
  2. 装饰者模式可以动态地扩展一个实现类的功能,且可以无限制地使用装饰模式。
  3. 具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”。

缺点

  1. 多层装饰比较复杂。
  2. 装饰模式会导致设计中出现许多小类,如果过度使用会使程序变得很复杂。

6.Java的实现例子

我们将以Beverage(饮料)作为抽象组件,并有一个具体的Coffee(咖啡)实现。我们将为咖啡添加一些装饰者,如Milk(牛奶)和Sugar(糖)。

首先,定义Beverage接口和Coffee类:

java">// 抽象组件:Beverage  
public interface Beverage {  String getDescription();  double cost();  
}  // 具体组件:Coffee  
public class Coffee implements Beverage {  @Override  public String getDescription() {  return "Coffee";  }  @Override  public double cost() {  return 2.0;  }  
}

接下来,定义Decorator类,它实现了Beverage接口并持有一个Beverage对象的引用:

java">// 装饰者:Decorator  
public abstract class Decorator implements Beverage {  protected Beverage beverage;  public Decorator(Beverage beverage) {  this.beverage = beverage;  }  @Override  public String getDescription() {  return beverage.getDescription();  }  @Override  public double cost() {  return beverage.cost();  }  
}

现在,定义具体的装饰者类,如MilkSugar

java">// 具体装饰者:Milk  
public class Milk extends Decorator {  public Milk(Beverage beverage) {  super(beverage);  }  @Override  public String getDescription() {  return beverage.getDescription() + ", Milk";  }  @Override  public double cost() {  return beverage.cost() + 0.5;  }  
}  // 具体装饰者:Sugar  
public class Sugar extends Decorator {  public Sugar(Beverage beverage) {  super(beverage);  }  @Override  public String getDescription() {  return beverage.getDescription() + ", Sugar";  }  @Override  public double cost() {  return beverage.cost() + 0.3;  }  
}

最后,在主程序中使用装饰者:

java">public class BeverageTest {  public static void main(String[] args) {  Beverage beverage = new Coffee();  System.out.println(beverage.getDescription() + " $" + beverage.cost());  Beverage beverageWithMilk = new Milk(beverage);  System.out.println(beverageWithMilk.getDescription() + " $" + beverageWithMilk.cost());  Beverage beverageWithMilkAndSugar = new Sugar(beverageWithMilk);  System.out.println(beverageWithMilkAndSugar.getDescription() + " $" + beverageWithMilkAndSugar.cost());  }  
}

http://www.ppmy.cn/embedded/41928.html

相关文章

快速查看字符对应的ASCII码

1、借助gdb查看 打印字符串用双引号括起来打印单个字符用单引号括起来x 表示十六机制d 表示十进制t 表示二进制 2、借助二进制查看软件 第一步:把要查看的字符保存到文本文件中第二步:借助二进制查看工具(比如:Hex Editor Neo&am…

skimage图像处理(六)

在图像中绘制图形 绘制线条 格式rr,cc draw.line() from skimage import draw,data,io import matplotlib.pyplot as plt imgio.imread(c.jpg) rr,cc draw.line(6,150,660,450) draw.set_color(img,[rr,cc],[0,0,225]) #绘制颜色 plt.imshow(img,plt.cm.gray) 显…

根据标签最大层面ROI提取原始图像区域(二)

今天要实现的任务还是提取肿瘤的感兴趣区域。 有两个文件,一个是nii的原始图像文件,一个是nii的标签文件。我们要实现的是:在标签文件上选出最大层面,然后把最大层面的ROI映射到原始图像区域,在原始图像上提裁剪出ROI…

css中用来设置表格的一些样式属性

在CSS中我们用来给表格设置样式的有以下属性: 1. 基本表格样式 边框:使用border属性可以为表格添加边框。内边距:padding属性用于增加单元格内的空间。外边距:margin属性用于控制表格与其他元素之间的距离。 2. 表格结构样式 …

Nginx-04-Docker Nginx

Docker Nginx 实战 HTTP 服务 Nginx 的最大作用,就是搭建一个 Web Server。 有了容器,只要一行命令,服务器就架设好了,完全不用配置。 运行官方 image $ docker container run \-d \-p 8080:80 \--rm \--name mynginx \nginx…

UVM寄存器模型——手写Ralf问题debug

寄存器模型是UVM中至关重要的一部分,如果没有寄存器模型,那么验证平台对于DUT内寄存器的访问方式将十分有限,对DUT运行状态的把控也会变得更为复杂。 在验证过程中,scoreboard或者其他验证组件经常需要了解当前时间某个寄存器的值…

【Leetcode每日一题】 动态规划 - 简单多状态 dp 问题 - 删除并获得点数(难度⭐⭐)(76)

1. 题目解析 题目链接:LCR 091. 粉刷房子 这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。 2.算法原理 1. 状态定义 在解决这类问题时,我们首先需要根据题目的具体要求来定义状态。针对房屋粉刷问题&#…

【个人成长】Fitten Code 测试案例分析

JS,Fitten Code 当插件,然后在代码分析的时候,有些小感悟,大模型写代码的思路,正常我理解的代码思路。 输入代码 (item.score* 100).toFixed(0)Prompt 得出的结果 5分,如果超过100按100算输出结果 con…