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

server/2024/10/19 11:38:08/

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/server/42061.html

相关文章

那些年我与c++的叫板(一)--string类自实现

引子:我们学习了c中的string类,那我们能不能像以前数据结构一样自己实现string类呢?以下是cplusplus下的string类,我们参考参考! 废话不多说,直接代码实现:(注意函数之间的复用&…

leetcode刷题指南

本文我将分享给大家一套我自己使用良久并觉得非常高效的 学习论,它可以运用到 Leetcode 上的刷题,也可以 generalize 到生活中涉及到学习以及记忆的方方面面。当然,本文将以 Leetcode 刷题为 case study 去进行讲解。 更具体一点, 我会教大家…

ChatGPT-4o 实战 如何快速分析混淆加密和webpack打包的源码

ChatGPT-4o 几个特点 一个对话拥有长时间的记忆,可以连续上传文件,让其分析,最大一个代码文件只能3M,超出3M的文件,可以通过split-file可以进行拆分 其次ChatGPT-4o可以生成文件的下载链接,这有利于大文件的…

一文读懂云渲染与离线渲染的关系是什么

云渲染和离线渲染是什么关系呢?在渲染过程中经常会有人听到云渲染、离线渲染,然而两者的关系却有很多人都不清楚,下面一起来简单看看两者之间的关系吧。 1、渲染目的和过程: - 离线渲染:通常用于创建高质量的静态图像…

【嵌入式大赛应用赛道】机械手臂

电机 进步电机:它的转动是以确定的步数进行的,只要计算好脉冲数量和频率,就可以准确预测和控制电机的转动角度、速度以及停止的位置 伺服电机:将输入的电信号(如电压或电流指令)转换成轴上的精确旋转运动…

多区域OSPF路由配置

一、基础配置 1.搭建实验拓扑图 2.实验编址 具体如何配置可以看这一篇详细的博文:单区域OSPF实验-CSDN博客 3.分别检查六个路由器的配置: 使用命令display ip interface brief R1的配置 其他大家可以调出来,再与实验拓扑图进行比对&#…

如何部署TDE透明加密实现数据库免改造加密存储

安当TDE(透明数据加密)实现数据库加密的步骤主要包括以下几个部分: 准备安装环境:确保操作系统和数据库环境已经安装并配置好,同时确保具有足够的权限来安装和配置TDE透明加密组件。下载安装包:从官方网站…

【企业宣传片】拍摄思维提升,专业影视质感核心揭密,一课搞定

课程下载:【企业宣传片】拍摄-课程网盘链接提取码下载.txt资源-CSDN文库 更多资源下载:关注我。 课程介绍 大量案例分析宣传片拍摄的痛点要点 根据案例告诉你解决方案,讲透概念 改变你对企业宣传片的思维层级与认知 归纳总结对比不同案…