结构型模式4.装饰器模式

结构型模式

  1. 适配器模式(Adapter Pattern)
  2. 桥接模式(Bridge Pattern)
  3. 组合模式(Composite Pattern)
  4. 装饰器模式(Decorator Pattern)
  5. 外观模式(Facade Pattern)
  6. 享元模式(Flyweight Pattern)
  7. 代理模式(Proxy Pattern)

装饰器模式(Decorator Pattern)是一种结构型设计模式,旨在动态地给一个对象添加额外的功能,而不需要修改其结构。装饰器模式通过使用组合(而非继承)来扩展对象的功能,允许你在运行时对对象进行扩展。

装饰器模式的核心思想:

  • 不改变对象的原有功能,而是在原有功能的基础上增加新的功能
  • 通过将装饰功能封装在装饰器类中,使得功能的增加和修改更加灵活。
  • 装饰器模式通常与继承相对,继承会通过扩展类来增加功能,而装饰器模式是通过组合不同的装饰器对象来增强功能。

主要角色:

  1. Component(组件):定义了一个接口,通常是一个抽象类或者接口,规定了被装饰的对象和装饰器的共同接口。
  2. ConcreteComponent(具体组件):实现了Component接口的基本功能,是被装饰的目标对象。
  3. Decorator(装饰器):是一个抽象类,持有一个Component对象,并在其功能上进行扩展。它继承了Component接口,并将所有方法委托给实际的Component对象。
  4. ConcreteDecorator(具体装饰器):继承自Decorator,负责具体的功能扩展(例如添加新功能或修改现有功能)。

装饰器模式的示例:咖啡店

假设我们要设计一个咖啡的销售系统,其中有不同种类的咖啡(例如:单纯的黑咖啡、加了牛奶的咖啡、加了糖的咖啡等),每种咖啡在基础上都有不同的装饰。我们可以使用装饰器模式来动态地为咖啡添加不同的配料。

// 组件接口,所有的咖啡都实现这个接口
public interface Coffee {double cost(); // 计算价格String ingredients(); // 获取配料信息
}// 具体组件,代表普通的黑咖啡
public class BlackCoffee implements Coffee {@Overridepublic double cost() {return 5.0; // 黑咖啡的基础价格}@Overridepublic String ingredients() {return "Black Coffee"; // 黑咖啡的配料}
}// 装饰器,持有一个Coffee对象,并且可以增强其功能
public abstract class CoffeeDecorator implements Coffee {protected Coffee coffee; // 持有一个咖啡对象public CoffeeDecorator(Coffee coffee) {this.coffee = coffee;}@Overridepublic double cost() {return coffee.cost(); // 委托给被装饰的咖啡对象}@Overridepublic String ingredients() {return coffee.ingredients(); // 委托给被装饰的咖啡对象}
}// 装饰器1:添加牛奶
public class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee coffee) {super(coffee);}@Overridepublic double cost() {return coffee.cost() + 2.0; // 加牛奶的价格}@Overridepublic String ingredients() {return coffee.ingredients() + ", Milk"; // 牛奶的配料}
}// 装饰器2:添加糖
public class SugarDecorator extends CoffeeDecorator {public SugarDecorator(Coffee coffee) {super(coffee);}@Overridepublic double cost() {return coffee.cost() + 1.0; // 加糖的价格}@Overridepublic String ingredients() {return coffee.ingredients() + ", Sugar"; // 糖的配料}
}public class Client {public static void main(String[] args) {// 创建一个黑咖啡Coffee coffee = new BlackCoffee();System.out.println("Cost: " + coffee.cost()); // 输出:5.0System.out.println("Ingredients: " + coffee.ingredients()); // 输出:Black Coffee// 给黑咖啡添加牛奶coffee = new MilkDecorator(coffee);System.out.println("Cost: " + coffee.cost()); // 输出:7.0System.out.println("Ingredients: " + coffee.ingredients()); // 输出:Black Coffee, Milk// 给已经添加牛奶的咖啡再添加糖coffee = new SugarDecorator(coffee);System.out.println("Cost: " + coffee.cost()); // 输出:8.0System.out.println("Ingredients: " + coffee.ingredients()); // 输出:Black Coffee, Milk, Sugar}
}

解释:

  • Component(Coffee):定义了咖啡的基础功能,所有的咖啡类都实现了这个接口,提供 cost() 和 ingredients() 方法。
  • ConcreteComponent(BlackCoffee):表示一种具体的咖啡(黑咖啡),实现了 Coffee 接口。
  • Decorator(CoffeeDecorator):是一个抽象类,持有一个 Coffee 对象,允许在此基础上添加新功能。
  • ConcreteDecorator(MilkDecorator 和 SugarDecorator):具体装饰器,分别为咖啡添加牛奶和糖。它们在原有功能的基础上进行扩展。

装饰器模式的优缺点:

优点:
  1. 增强灵活性:装饰器模式允许动态地向对象添加功能,而不需要修改原有对象的代码。这种方式比继承更灵活。
  2. 减少子类的创建:通过装饰器模式,我们不需要为每一种不同的组合创建一个子类,而是通过不同的装饰器组合出所需的功能。
  3. 符合开闭原则:装饰器模式遵循开闭原则,即可以对功能进行扩展而不需要修改原有代码。
缺点:
  1. 装饰器过多时,系统会变得很复杂:如果装饰器链太长,可能会造成代码的复杂度增加,使得调试和理解变得更加困难。
  2. 可能导致过多的小对象:每个装饰器本身就是一个对象,因此在复杂的系统中,可能会创建大量的小对象,增加内存开销。

总结:

装饰器模式通过将功能与对象的实现分离,使得我们能够在运行时动态地增加对象的功能,而不需要修改对象本身。它能够灵活地扩展对象功能,减少了子类数量,提升了系统的灵活性和可维护性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/66549.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

el-table 自定义表头颜色

第一种方法&#xff1a;计算属性 <template><div><el-table:data"formData.detail"border stripehighlight-current-row:cell-style"{ text-align: center }":header-cell-style"headerCellStyle"><el-table-column fixed…

C#标识符和关键字

本文将学习两个重要的基本概念&#xff1a;标识符和关键字。 1. 标识符 我们继续秉承"从实践中学习"的理念&#xff0c;先来看一段代码&#xff0c;如代码清单3-1所示。 代码清单3-1 标识符 using System;namespace ProgrammingCSharp4 {class IdentifierSample{…

怎么管理电脑usb接口,分享四种USB端口管理方法

怎么管理电脑usb接口&#xff0c;分享四种USB端口管理方法 USB接口作为电脑重要的外部接口&#xff0c;方便了数据传输和设备连接。 然而&#xff0c;不加管理的USB接口也可能带来安全隐患&#xff0c;例如数据泄露、病毒传播等。 因此&#xff0c;有效管理电脑USB接口至关重…

从 TiDB 学习分布式数据库测试

前言 最近在研究数据库正确性测试相关的内容&#xff0c;恰好看到TiDB数据库在这方面的工作&#xff0c;很受启发&#xff0c;故写此文章。 推荐下一些TiDB官方好文章&#xff1a; 《分布式系统测试那些事儿 – 理念》https://cn.pingcap.com/blog/distributed-system-test-…

尚硅谷Vue3入门到实战 —— 04 OptionsAPI 与 CompositionAPI

我们看一下上一节的代码&#xff0c;如下&#xff1a; <template><div class"person"><h2>姓名&#xff1a; {{ name }}</h2><h2>年龄&#xff1a; {{ age }}</h2><button click"changeName">修改名字</but…

【物联网原理与运用】知识点总结(上)

目录 名词解释汇总 第一章 物联网概述 1.1物联网的基本概念及演进 1.2 物联网的内涵 1.3 物联网的特性——泛在性 1.4 物联网的基本特征与属性&#xff08;五大功能域&#xff09; 1.5 物联网的体系结构 1.6 物联网的关键技术 1.7 物联网的应用领域 第二章 感知与识别技术 2.1 …

Nginx:会话保持

会话保持 是指在负载均衡环境中,确保来自同一用户的多个请求都发送到同一个后端服务器。这通常用于那些需要记住用户状态或上下文的应用程序,例如购物车、登录状态等。 会话保持的重要性 用户体验:保证用户在整个会话期间的一致性体验,避免因不同服务器间的数据不同步导致…

SEO内容优化:如何通过用户需求赢得搜索引擎青睐?

在谷歌SEO优化中&#xff0c;内容一直是最重要的因素之一。但要想让内容真正发挥作用&#xff0c;关键在于满足用户需求&#xff0c;而不是简单地堆砌关键词。谷歌的算法越来越智能化&#xff0c;更注重用户体验和内容的实用性。 了解目标用户的需求。通过工具如Google Trends…

Clisoft SOS与CAD系统集成

Clisoft SOS与CAD系统集成 以下内容大部分来自官方文档&#xff0c;目前只用到与Cadence Virtuoso集成&#xff0c;其他还未用到&#xff0c;如有问题或相关建议&#xff0c;可以留言。 与Keysight ADS集成 更新SOS客户端配置文件sos.cfg&#xff0c;以包含支持ADS的模板&am…

Unity-Mirror网络框架从入门到精通之Attributes属性介绍

前言 在现代游戏开发中&#xff0c;网络功能日益成为提升游戏体验的关键组成部分。Mirror是一个用于Unity的开源网络框架&#xff0c;专为多人游戏开发设计。它使得开发者能够轻松实现网络连接、数据同步和游戏状态管理。本文将深入介绍Mirror的基本概念、如何与其他网络框架进…

【计算机视觉】单目深度估计模型-Depth Anything-V2

概述 本篇将简单介绍Depth Anything V2单目深度估计模型&#xff0c;该模型旨在解决现有的深度估计模型在处理复杂场景、透明或反射物体时的性能限制。与前一代模型相比&#xff0c;V2版本通过采用合成图像训练、增加教师模型容量&#xff0c;并利用大规模伪标签现实数据进行学…

uni-app图文列表到详情页面切换

需求&#xff1a;参考若依框架后&#xff0c;想实现首页浏览文章列表&#xff0c;没有合适的样式参考&#xff0c;所以需要有效果做到“图文列表到详情页面切换”&#xff0c;查阅了一下案例 发现有相应的案例&#xff0c;在导航栏“模板”中找到了 DCloud 插件市场 PC电脑端访…

日志服务 SQL 引擎全新升级

作者&#xff1a;戴志勇、顾汉杰&#xff08;执少&#xff09; SQL 作为 SLS 基础功能&#xff0c;每天承载了用户大量日志数据的分析请求&#xff0c;既有小数据量的快速查询&#xff08;如告警、即席查询等&#xff09;&#xff1b;也有上万亿数据规模的报表级分析。SLS 作为…

【微服务】5、服务保护 Sentinel

Sentinel学习内容概述 Sentinel简介与结构 Sentinel是Spring Cloud Alibaba的组件&#xff0c;由阿里巴巴开源&#xff0c;用于服务流量控制和保护。其内部核心库&#xff08;客户端&#xff09;包含限流、熔断等功能&#xff0c;微服务引入该库后只需配置规则。规则配置方式有…

matlab编写Newton插值多项式

定义&#xff1a; 即&#xff1a; clear x [1, 2, 3, 4]; % x坐标 y [2, 1, 4, 3]; % y坐标 % 定义目标插值点 xi 2.5;% x: 已知数据点的x坐标% y: 已知数据点的y坐标% xi: 插值点&#xff0c;可以是一个数或一个向量n length(x);% 初始化差商矩阵F zeros(n, n);F(:,1…

unity学习14:unity里的C#脚本的几个基本生命周期方法, 脚本次序order等

目录 1 初始的C# 脚本 1.1 初始的C# 脚本 1.2 创建时2个默认的方法 2 常用的几个生命周期方法 2.1 脚本的生命周期 2.1.1 其中FixedUpdate 方法 的时间间隔&#xff0c;是在这设置的 2.2 c#的基本语法别搞混 2.2.1 基本的语法 2.2.2 内置的方法名&#xff0c;要求更严…

东土科技参股广汽集团飞行汽车初创公司,为低空经济构建新型产业生态

近日&#xff0c;广汽集团旗下专注于飞行汽车领域的初创公司广东高域科技有限公司于2024年12月31日正式成立&#xff0c;在穿透后的股东信息中&#xff0c;东土科技通过广州瓴云科技投资合伙企业&#xff08;有限合伙&#xff09;赫然在列。 此前12月18日&#xff0c;广汽集团…

基于Elasticsearch8的向量检索实现相似图形搜索

Elasticsearch8版本增加了KNN向量检索&#xff0c;可以基于此功能实现以图搜图功能。 1、首先创建索引&#xff0c;es提供了类型为dense_vector的字段&#xff0c;用于存储向量&#xff0c;其中dims是向量维度&#xff0c;可以不配置&#xff0c;es会根据第一条插入的向量维度…

PHP如何删除数组中的特定值?

php 中删除数组特定值的方法有三种&#xff1a;unset()&#xff1a;直接删除指定索引的值&#xff0c;但会保留数组索引结构和未删除元素&#xff0c;适合小数组。array_filter()&#xff1a;根据自定义回调函数筛选数组元素&#xff0c;返回一个新数组&#xff0c;原数组不变&…

计算效率提升 10 倍,存储成本降低 60%,灵犀科技基于 Apache Doris 建设统一数据服务平台

导读&#xff1a;灵犀科技早期基于 Hadoop 构建大数据平台&#xff0c;在战略调整和需求的持续扩增下&#xff0c;数据处理效率、查询性能、资源成本问题随之出现。为此&#xff0c;引入 Apache Doris 替换了复杂技术栈&#xff0c;升级为集存储、加工、服务为一体的统一架构&a…