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

结构型设计模式(二)装饰器模式 适配器模式

 

6b6fa1c626f5a61327c21c861ed353cb.png

装饰器模式 Decorator

1、什么是装饰器模式

装饰器模式允许通过将对象放入特殊的包装对象中来为原始对象添加新的行为。这种模式是一种结构型模式,因为它通过改变结构来改变被装饰对象的行为。它涉及到一组装饰器类,这些类用来包装具体组件。

2、为什么使用装饰器模式

  1. 灵活性:装饰器模式允许在运行时动态地为对象添加新的行为,而无需修改其代码,提供了一种灵活的方式来扩展对象的功能。
  2. 避免子类爆炸:通过使用装饰器模式,可以避免创建大量子类来扩展对象的功能,从而避免了子类爆炸的问题。
  3. 组合功能:可以通过组合多个装饰器来实现复杂的功能组合,无需使用大量的继承关系。

3、如何使用装饰器模式

设计实现咖啡订单系统,包含基本咖啡和不同的配料作为装饰器

// 抽象组件 - 咖啡
interface Coffee {String getDescription();double cost();
}// 具体组件 - 基本咖啡
class BasicCoffee implements Coffee {@Overridepublic String getDescription() {return "Basic Coffee";}@Overridepublic double cost() {return 3.0;}
}// 抽象装饰器
abstract class CoffeeDecorator implements Coffee {protected Coffee decoratedCoffee;public CoffeeDecorator(Coffee decoratedCoffee) {this.decoratedCoffee = decoratedCoffee;}@Overridepublic String getDescription() {return decoratedCoffee.getDescription();}@Overridepublic double cost() {return decoratedCoffee.cost();}
}// 具体装饰器 - 牛奶
class MilkDecorator extends CoffeeDecorator {public MilkDecorator(Coffee decoratedCoffee) {super(decoratedCoffee);}@Overridepublic String getDescription() {return super.getDescription() + ", Milk";}@Overridepublic double cost() {return super.cost() + 1.0;}
}// 具体装饰器 - 糖
class SugarDecorator extends CoffeeDecorator {public SugarDecorator(Coffee decoratedCoffee) {super(decoratedCoffee);}@Overridepublic String getDescription() {return super.getDescription() + ", Sugar";}@Overridepublic double cost() {return super.cost() + 0.5;}
}// 客户端代码
public class Client {public static void main(String[] args) {// 创建基本咖啡Coffee basicCoffee = new BasicCoffee();System.out.println("Description: " + basicCoffee.getDescription());System.out.println("Cost: $" + basicCoffee.cost());// 添加牛奶装饰器Coffee milkCoffee = new MilkDecorator(basicCoffee);System.out.println("Description: " + milkCoffee.getDescription());System.out.println("Cost: $" + milkCoffee.cost());// 添加糖装饰器Coffee sugarMilkCoffee = new SugarDecorator(milkCoffee);System.out.println("Description: " + sugarMilkCoffee.getDescription());System.out.println("Cost: $" + sugarMilkCoffee.cost());}
}

4、是否存在缺陷和不足

  1. 可能导致类爆炸:有大量具体组件和装饰器时,可能导致类的数量急剧增加,增加了系统的复杂性。
  2. 破坏封装性:装饰器模式将具体组件暴露给装饰器类,可能破坏了封装性。

5、如何缓解缺陷和不足

  1. 使用抽象工厂:结合抽象工厂模式,通过工厂来创建组件和装饰器,降低类的数量。
  2. 使用组合模式:将具体组件和装饰器组织成树形结构,使用组合模式来管理它们的关系。
  3. 慎用过多装饰器:在设计时慎用过多的装饰器,确保仅在需要时使用,以避免类爆炸问题。

适配器模式 Adapter

1、什么是适配器模式

适配器模式允许原本由于接口不匹配而无法在一起工作的类能够协同工作。它通过引入一个包装类,即适配器,来转换原有类的接口为客户端期望的接口。

2、为什么使用适配器模式

  1. 解耦性:适配器模式允许客户端与目标类的实现细节解耦,使得客户端不需要知道目标类的内部实现。
  2. 复用性:适配器模式可以使得已有的类在新的系统中复用,而无需修改其代码。
  3. 灵活性:适配器模式允许在不改变现有代码的情况下引入新的类,提高系统的灵活性。

3、如何使用适配器模式

// 目标接口
interface Target {void request();
}// 不兼容的类
class Adaptee {public void specificRequest() {System.out.println("Adaptee's specificRequest");}
}// 适配器类
class Adapter implements Target {private Adaptee adaptee;public Adapter(Adaptee adaptee) {this.adaptee = adaptee;}@Overridepublic void request() {adaptee.specificRequest();}
}// 客户端代码
public class Client {public static void main(String[] args) {Adaptee adaptee = new Adaptee();Target target = new Adapter(adaptee);target.request();}
}

4、是否存在缺陷和不足

  1. 可能导致过多的适配类:如果系统中有多个不同的类需要适配,可能会导致大量的适配器类,使系统变得复杂。
  2. 不支持多继承的语言的限制:在一些不支持多继承的语言中,适配器模式可能会受到限制。

5、如何缓解缺陷和不足

  1. 使用对象适配器而非类适配器:对象适配器通过组合的方式引入被适配对象,避免了类适配器的多继承问题。
  2. 考虑使用接口适配器:如果目标接口中定义的方法较多,可以考虑使用接口适配器模式,只需实现感兴趣的方法。

 

相关文章:

结构型设计模式(二)装饰器模式 适配器模式

装饰器模式 Decorator 1、什么是装饰器模式 装饰器模式允许通过将对象放入特殊的包装对象中来为原始对象添加新的行为。这种模式是一种结构型模式,因为它通过改变结构来改变被装饰对象的行为。它涉及到一组装饰器类,这些类用来包装具体组件。 2、为什…...

C#数据结构

C#数据结构 常见结构 1、集合 2、线性结构 3、树形结构 4、图形结构 Array/ArrayList/List 特点:内存上连续存储,节约空间,可以索引访问,读取快,增删慢 using System; namespace ArrayApplication {class MyAr…...

代码随想Day39 | 62.不同路径、63. 不同路径 II

62.不同路径 每次向右或者向下走两个选择,定义dp数组dp[i][j] 为到达索引ij的路径和,状态转移公式为 dp[i][j]dp[i-1][j]dp[i][j-1],初始状态的第一行和第一列为1,从左上到右下开始遍历即可。详细代码如下: class Sol…...

Autosar通信实战系列07-Com模块要点及其配置介绍(二)

本文框架 前言1. ComGeneral配置2. ComConfig配置2.1 ComGwMapping2.2 ComIPdus2.3 ComIPduGroups2.4 ComIPduSignals2.5 ComIPduSignalGroups2.6 ComTimeBasis前言 在本系列笔者将结合工作中对通信实战部分的应用经验进一步介绍常用,包括但不限于通信各模块的开发教程,代码…...

DSP捕获输入简单笔记

之前使用stm32的大概原理是: 输入引脚输入一个脉冲,捕获1开始极性捕获,捕获的是从启动捕获功能开始计数,捕获的是当前的计数值; 例如一个脉冲,捕获1捕获上升沿,捕获2捕获下降沿;而两…...

【Java基础】HashMap 原理

文章目录 1、HashMap 设置值的原理2、HashMap 获取值原理3、HashMap Hash优化4、HashMap 寻址优化5、HashMap 是如何解决Hash冲突的?5.1 get数据的时候,如果定位到指定位置的元素是一个链表,怎么办呢?5.2 红黑树 6、数组扩容6.1 数…...

vue3的大致使用

<template><div class"login_wrap"><div class"form_wrap"> <!-- 账号输入--> <el-form ref"formRef" :model"user" class"demo-dynamic" > <!--prop要跟属性名称对应-->…...

什么是计算机网络?计算机网络基础知识

1.网络的组成部分&#xff1a;由主机&#xff0c;路由器&#xff0c;交换机等组成 2.网络结构&#xff1a;网络的网络 3.信息交换方式&#xff1a;电路交换和分组交换 4.网络分层&#xff1a;分清职责&#xff0c;物理层&#xff0c;链路层&#xff0c;网络层&#xff0c;运…...

【机器学习 | 假设检验系列】假设检验系列—卡方检验(详细案例,数学公式原理推导),最常被忽视得假设检验确定不来看看?

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…...

RealBasicVSR高清处理视频

autodl做了镜像&#xff1a;高清RealBasicVSR 首先在剪映将视频剪好导出&#xff0c;最多是720像素的&#xff0c;不然后面超分的时候会爆显存。剪映视频也最好是双数帧数结尾的&#xff0c;不然超分的时候单数图片会报错->RuntimeError: non-empty 3D or 4D input tensor …...

晚期食管癌肿瘤治疗线程分类

文章目录 1、肿瘤治疗的线数1.1 基础概念1.2 线程定义1.3 如何计算治疗线数 2 食管癌治疗指南2.1 食管癌诊疗指南2.1 CSCO 本文前半部分主要来源于参考文件1&#xff0c;其余部分来源于官方指南。无原创内容&#xff0c;全部为摘要。 1、肿瘤治疗的线数 1.1 基础概念 抗肿瘤药…...

高效营销系统集成:百度营销的API无代码解决方案,提升电商与广告效率

百度营销API连接&#xff1a;构建无代码开发的高效集成体系 在数字营销的高速发展时代&#xff0c;企业追求的是快速响应市场的能力以及提高用户运营的效率。百度营销API连接正是为此而生&#xff0c;它通过无代码开发的方式&#xff0c;实现了电商平台、营销系统和CRM的一站式…...

网络基础(十一):VRRP原理与配置

目录 前言&#xff1a; 1、VRRP的基本概述 2、VRRP的基本原理 2.1VRRP的基本结构 2.2设备类型 2.3状态机 2.4VRRP路由器的抢占功能 2.5VRRP路由器的优先级 2.6VRRP工作原理 2.7主备路由器的工作内容 3、VRRP的基本配置 3.1配置主路由器和备用路由器 3.2配置PC1与P…...

设计模式——状态模式

引言 状态模式是一种行为设计模式&#xff0c; 让你能在一个对象的内部状态变化时改变其行为&#xff0c; 使其看上去就像改变了自身所属的类一样。 问题 状态模式与有限状态机 的概念紧密相关。 其主要思想是程序在任意时刻仅可处于几种有限的状态中。 在任何一个特定状态中…...

2020-XNUCA babyv8

做的第一道存在指针压缩机制的V8题&#xff0c;通过小越界写修改length构造大越界读写&#xff0c;然后利用arraybuffer的backing store构造任意地址写&#xff0c;利用wasm rwx段地址的特点以及堆空间的分布&#xff0c;搜索到rwx段的具体地址&#xff0c;然后利用任意地址写将…...

货物数据处理pandas版

1求和 from openpyxl import load_workbook import pandas as pddef print_hi(name):# Use a breakpoint in the code line below to debug your script.print(fHi, {name}) # Press CtrlF8 to toggle the breakpoint.# Press the green button in the gutter to run the scr…...

MC-30A (32.768 kHz用于汽车应用的晶体单元)

MC-30A 32.768 kHz用于汽车应用的晶体&#xff0c;车规晶振中的热销型号之一。该款石英晶体谐振器&#xff0c;可以在-40 to 85 C的温度内稳定工作&#xff0c;能满足起动振动的要求。同时满足AEC-Q200无源元件质量标准认证&#xff0c;满足汽车仪表系统的所有要求。 频率范围…...

TrustZone之其他设备及可信基础系统架构

一、其他设备 最后,我们将查看系统中的其他设备,如下图所示: 我们的示例TrustZone启用的系统包括一些尚未涵盖的设备,但我们需要这些设备来构建一个实际的系统。 • 一次性可编程存储器(OTP)或保险丝 这些是一旦写入就无法更改的存储器。与每个芯片上都包含相同…...

自由编程学习资源:free-programming-books

最近&#xff0c;我发现了一个在GitHub上备受欢迎的项目&#xff0c;它为程序员和编程爱好者提供了丰富、免费且高质量的学习资料&#xff0c;这就是"free-programming-books"。目前&#xff0c;这个项目在GitHub上已经有305k的star&#xff0c;显示出它在开发者社区…...

饥荒Mod 开发(十三):木牌传送

饥荒Mod 开发(十二)&#xff1a;一键制作 饥荒Mod 开发(十四)&#xff1a;制作屏幕弹窗 一键传送源码 饥荒的地图很大&#xff0c;跑地图太耗费时间和饥饿值&#xff0c;如果大部分时间都在跑图真的是很无聊&#xff0c;所以需要有一个能够传送的功能&#xff0c;不仅可以快速…...

Qt/C++音视频开发60-坐标拾取/按下鼠标获取矩形区域/转换到视频源真实坐标

一、前言 通过在通道画面上拾取鼠标按下的坐标&#xff0c;然后鼠标移动&#xff0c;直到松开&#xff0c;根据松开的坐标和按下的坐标&#xff0c;绘制一个矩形区域&#xff0c;作为热点或者需要电子放大的区域&#xff0c;拿到这个坐标区域&#xff0c;用途非常多&#xff0…...

Java实现订单超时未支付自动取消的8种方法总结

Java实现订单超时未支付自动取消的8种方法总结 定时轮询 数据库定时轮询方式&#xff0c;实现思路比较简单。启动一个定时任务&#xff0c;每隔一定时间扫描订单表&#xff0c;查询到超时订单就取消。优点&#xff1a;实现简单。缺点&#xff1a;轮询时间间隔不好确定&#x…...

android动态权限申请并展示权限使用说明

# ExplainPermissions 动态权限申请并展示权限使用说明 随着工信部对APP的一系列整治&#xff0c;现在用户对于APP在使用时动态申请的权限是比较敏感的&#xff0c;为了更好的用户体验&#xff0c;我们可以在权限动态申请的时候一并向用户展示所需要申请权限的使用说明。这样用…...

论文阅读《DPS-Net: Deep Polarimetric Stereo Depth Estimation》

论文地址&#xff1a;https://openaccess.thecvf.com/content/ICCV2023/html/Tian_DPS-Net_Deep_Polarimetric_Stereo_Depth_Estimation_ICCV_2023_paper.html 概述 立体匹配模型难以处理无纹理场景的匹配&#xff0c;现有的方法通常假设物体表面是光滑的&#xff0c;或者光照是…...

docker文档转译1

写在最前面 本文主要是转译docker官方文档。主题是Docker overview&#xff0c;这里是链接 Docker概述 Docker是一个用于开发、发布和运行应用程序的开放平台。Docker使你能够将应用程序与基础设施分离&#xff0c;从而可以快速交付软件。你可以使用相同的方法像管理应用程序…...

UE4 图片环形轮播 蓝图

【需求】 图片环形轮播 任意图片之间相互切换 切换图片所需时间均为1s 两个图片之间切换使用就近原则 播放丝滑无闪跳 【Actor的组成】 每个图片的轴心都在原点 【蓝图节点】...

饥荒Mod 开发(十):制作一把AOE武器

饥荒Mod 开发(九)&#xff1a;物品栏排列 饥荒Mod 开发(十一)&#xff1a;修改物品堆叠 前面的文章介绍了很多基础知识以及如何制作一个物品&#xff0c;这次制作一把武器&#xff0c;装备之后可以用来攻击怪物。 制作武器贴图和动画 1.1 制作贴图。 先准备一张武器的贴图&a…...

微服务实战系列之ZooKeeper(下)

前言 通过前序两篇关于ZooKeeper的介绍和总结&#xff0c;我们可以大致理解了它是什么&#xff0c;它有哪些重要组成部分。 今天&#xff0c;博主特别介绍一下ZooKeeper的一个核心应用场景&#xff1a;分布式锁。 应用ZooKeeper Q&#xff1a;什么是分布式锁 首先了解一下&…...

FFmpeg项目的组成

主要由三个部分组成&#xff1a; 工具 ffmpeg&#xff1a;用于音视频转码、转换ffplay&#xff1a;音视频播放器ffserver&#xff1a;流媒体服务器ffprobe&#xff1a;多媒体码流分析器 SDK 这个部分是供开发者使用的SDK&#xff0c;SDK是编译好的库。基本上每个平台都有对…...

计算机网络:数据链路层(广域网、PPP协议、HDLC协议)

今天又学会了一个知识&#xff0c;加油&#xff01; 目录 一、广域网 二、PPP协议 1、PPP协议应满足的要求 2、PPP协议无需满足的要求 3、PPP协议的三个组成部分 4、PPP协议的状态图 5、PPP协议的帧格式 三、HDLC协议 1、HDLC的站&#xff08;主站、从站、复合站&…...

手机网站焦点图代码/百度入口网页版

HADDR HADDR是来自AHB总线上地址线&#xff0c;是字节地址。连接到FSMC_A[25:0]&#xff0c;再连接到外部的存储器&#xff0c; 地址线 首先明确一点&#xff0c;26根地址线&#xff0c;它是26个位。它的寻址空间或者寻址容量是2^26&#xff0c;单位是Byte。HADDR是字节地址…...

春播网站是谁做的/网站推广平台排行

一个&#xff1a;java 和c参考控制他提到引用&#xff0c;我们会想到java它不喜欢c里面的指针。当然java内引用和c里面的引用是不同的。比如&#xff1a;比方C中&#xff0c;我对某一个函数的声明。int a(int &b)&#xff0c;b即为引用类型&#xff0c;函数内b的改动能够影…...

有没有如何做网站的书/可以看封禁网站的浏览器

中国零售巨头阿里巴巴&#xff08;BABA.US&#xff09;旗下的云计算部门&#xff08;简称阿里云&#xff09;&#xff0c;近日开设首家英国数据中心&#xff0c;并在伦敦设有两个运营点。 据了解&#xff0c;英国大区上线了众多云计算产品&#xff0c;包括弹性计算、云存储、数…...

东莞网站推广怎么做/潍坊seo建站

预计更新第一章. Python 简介 Python 简介和历史Python 特点和优势安装 Python 第二章. 变量和数据类型 变量和标识符基本数据类型&#xff1a;数字、字符串、布尔值等字符串操作列表、元组和字典 第三章. 控制语句和函数 分支结构&#xff1a;if/else 语句循环结构&#…...

点击图片预览 wordpress/郑州seo网站排名

目前智能顾问已掌握大量资产&#xff0c;第一个以人工智能驱动的基金Rebellion曾成功预测了2008年股市崩盘&#xff0c;并在2009年给希腊债券F评级&#xff0c;而当时惠誉的评级仍然为A&#xff0c;通过人工智能&#xff0c;Rebellion比官方降级提前一个月&#xff1b;掌管900亿…...

网站开发客户需求/好看的web网页

需要设置代理的地方有三个 eclipse设定->一般->ネットワーク接続- 选 マニュアル 添加Http&#xff0c;Https&#xff0c;Socks代理 在下面添加例外 mavenusers文件夹下的.m2文件夹下的setting.xml 或者安装目录下conf文件夹中设置全局设置 <proxies> <prox…...