当前位置: 首页 > news >正文

设计模式大白话之装饰者模式

想象一下,你走进一家咖啡馆,点了一杯美式咖啡。但是,你可能还想根据自己的口味添加一些东西,比如奶泡、巧克力粉、焦糖酱或是肉桂粉。每次你添加一种配料,你的咖啡就会变得更丰富,同时价格也会相应增加。

在软件设计中,装饰者模式就是让你能够在不改变原始对象的情况下,动态地给它添加新功能或增强现有功能。这就好比你在咖啡上加配料,不是通过制作一种全新的咖啡,而是通过在现有的基础上增加东西。

比如,假设你正在开发一个文本编辑器,你希望用户可以选择开启一些额外的功能,比如语法高亮、行号显示、自动完成等。你不想为每一种可能的组合都创建一个单独的文本编辑器类,因为那样会有无数种组合,维护起来会非常困难。

这时,装饰者模式就派上用场了。你可以创建一个基本的文本编辑器类,然后为每一个额外功能创建一个装饰者类。当用户选择开启某项功能时,你就在基本的文本编辑器上“装饰”上相应的装饰者。这样,用户就可以根据自己的需求,动态地定制他们自己的文本编辑器,而不需要重新编写整个程序。

简而言之,装饰者模式就像是给你的软件产品添加“配料”,让它变得更有个性,更符合用户的需求,而无需更改其核心结构。

 以一家奶茶店为例,使用装饰者模式来动态地给奶茶添加各种配料。我们将创建一个基础的奶茶类,然后使用装饰者类来添加不同的配料,如珍珠、布丁、红豆、仙草、芝士等。

首先,我们定义奶茶的基本接口:
public abstract class Drink {// 基本属性protected String description = "Unknown Drink";// 获取描述public String getDescription() {return description;}// 设置描述public void setDescription(String description) {this.description = description;}// 抽象方法,计算价格public abstract double cost();
}
接下来,我们创建基础的奶茶类:
public class MilkTea extends Drink {public MilkTea() {description = "Milk Tea";}public double cost() {return 3.5; // 假设一杯基础奶茶的价格是3.5元}
}
然后,我们定义装饰者基类:
public abstract class AddOns extends Drink {protected Drink drink;public AddOns(Drink drink) {this.drink = drink;}public String getDescription() {return drink.getDescription();}public double cost() {return drink.cost();}
}
接着,我们创建具体的配料装饰者:
public class Boba extends AddOns {public Boba(Drink drink) {super(drink);}@Overridepublic String getDescription() {// 返回被装饰对象的描述return super.getDescription()+",  with Boba";}@Overridepublic double cost() {return drink.cost() + 1.0; // 添加珍珠的成本}
}
public class Pudding extends AddOns {public Pudding(Drink drink) {super(drink);}@Overridepublic String getDescription() {// 返回被装饰对象的描述return super.getDescription()+", with Pudding";}@Overridepublic double cost() {return drink.cost() + 0.8; // 添加布丁的成本}
}
public class RedBeans extends AddOns {public RedBeans(Drink drink) {super(drink);}@Overridepublic String getDescription() {// 返回被装饰对象的描述return super.getDescription()+",  with Red Beans";}@Overridepublic double cost() {return drink.cost() + 0.7; // 添加红豆的成本}
}
最后,在主函数中使用这些装饰者:
public class Main {public static void main(String[] args) {Drink milkTea = new MilkTea();System.out.println(milkTea.getDescription() + ": " + milkTea.cost());Drink milkTeaWithBoba = new Boba(milkTea);System.out.println(milkTeaWithBoba.getDescription() + ": " +  milkTeaWithBoba.cost());Drink milkTeaWithBobaAndPudding = new Pudding(milkTeaWithBoba);System.out.println(milkTeaWithBobaAndPudding.getDescription() + ": " + milkTeaWithBobaAndPudding.cost());Drink milkTeaWithBobaAndRedBeans = new RedBeans(milkTeaWithBoba);System.out.println(milkTeaWithBobaAndRedBeans.getDescription() + ": " + milkTeaWithBobaAndRedBeans.cost());}
}
执行结果
Milk Tea: 3.5
Milk Tea,  with Boba: 4.5
Milk Tea,  with Boba, with Pudding: 5.3
Milk Tea,  with Boba,  with Red Beans: 5.2

在上述代码中,Drink 是奶茶及其配料的抽象基类,MilkTea 是基本的奶茶实现,AddOns 是所有配料的基类,而Boba, Pudding, RedBeans 分别是具体的配料装饰者。通过组合不同的装饰者,我们可以轻松地构建出各种不同配料组合的奶茶,而且这些组合是在运行时动态决定的。

理解这种思想然后之后就是如何熟练运用,在有需要的时候。

http://www.lryc.cn/news/401278.html

相关文章:

  • 动手学深度学习6.3 填充和步幅-笔记练习(PyTorch)
  • 函数的形状怎么定义?
  • Windows 虚拟机服务器项目部署
  • JDBC(2)基础篇2——增删改查及常见问题
  • JVM知识点梳理
  • 产品经理-一份标准需求文档的8个模块(14)
  • 如何用一个例子向10岁小孩解释高并发实时服务的单线程事件循环架构
  • 如何为帕金森病患者选择合适的步行辅助设备?
  • 【排序算法】1.冒泡排序-C语言实现
  • Unity最新第三方开源插件《Stateful Component》管理中大型项目MonoBehaviour各种序列化字段 ,的高级解决方案
  • Spark SQL----INSERT TABLE
  • socket功能定义和一般模型
  • 如何在linux中给vim编辑器添加插件
  • Web 中POST为什么会发送两次请求
  • C语言经典程序100案例
  • 南京邮电大学统计学课程实验3 用EXCEL进行方差分析 指导
  • 2024-07-13 Unity AI状态机2 —— 项目介绍
  • shell脚本-linux如何在脚本中远程到一台linux机器并执行命令
  • Spring Data Redis + Redis数据缓存学习笔记
  • 在项目中,如何使用springboot+vue+springsecurity+redis缓存+Axios+MySQL数据库+mybatis
  • 微调 Florence-2 - 微软的尖端视觉语言模型
  • 【数据结构】二叉树全攻略,从实现到应用详解
  • 微信小程序加载动画文件
  • [计算机网络] VPN技术
  • SQL 中的 EXISTS 子句:探究其用途与应用
  • OpenSearch分析WAF日志
  • 【前端】零基础学会编写CSS
  • Day07-ES集群加密,kibana的RBAC实战,zookeeper集群搭建,zookeeper基本管理及kafka单点部署实战
  • RK3568 V1.4.0 SDK,USB OTG端子不能被电脑识别出adb设备,解决
  • 如何在 Ubuntu 14.04 服务器上使用 Nginx 安装和保护 phpMyAdmin