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

设计模式之适配器与装饰器

目录

适配器模式

简介

角色

使用

优缺点

使用场景

装饰器模式

简介

优缺点

模式结构

使用

使用场景


适配器模式

简介

允许将不兼容的对象包装成一个适配器类,使得其他类可以通过适配器类与原始对象进行交互,从而提高兼容性

角色

目标角色:该角色定义把其他类转换为何种接口,也就是我们的期望接口

源角色:你想把谁转换成目标角色,这个“谁”就是源角色,它是已经存在的、运行良好的类或对象

适配器角色:适配器模式的核心角色,其他两个角色都是已经存在的角色,而适配器角色是需要新建立的,它的职责非常简单:通过继承或是类关联的方式把源角色转换为目标角色

使用

1.定义目标接口:创建一个目标接口,这个接口定义了客户端所期望的功能。

2.创建原始类:客户端原始功能

3.创建适配器类:创建一个适配器类,该类实现了目标接口,同时包装了不兼容的原始对象,使得客户端可以通过目标接口与原始对象进行交互

4.使用目标接口:客户端代码使用目标接口与适配器进行交互

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

        目标接口Target,它定义了一个request方法。我们还有一个原始类Adaptee,它有一个名为specificRequest的方法。我们的适配器类Adapter实现了目标接口,并且包装了原始类的specificRequest方法。在客户端代码中,我们创建了一个原始类的实例和一个适配器类的实例,然后将适配器类的实例传递给目标接口的引用。当我们调用目标接口的request方法时,实际上是适配器类在调用原始类的specificRequest方法

优缺点

优点:

        1.能提高类的透明性和复用,现有的类复用但不需要改变。

        2.目标类和适配器类解耦,提高程序的扩展性。

        3.在很多业务场景中符合开闭原则

缺点:

        1.适配器编写过程需要全面考虑,可能会增加系统的复杂性

        2.增加代码阅读难度,降低代码可读性,过多使用适配器会使系统代码变得凌乱

使用场景

        1.一个类的接口转换成期望的另一个接口,使不能兼容的两个类一起工作

        2.想要创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作

        3.在软件维护期间,由于不同产品或不同厂家造成功能类似而接口不相同的情况,可以通过适配器模式来解决

        使用适配器模式可以降低不同组件之间的耦合度,提高系统的可扩展性和可维护性。同时,适配器模式还可以解决不同系统之间的接口不兼容问题

装饰器模式

简介

        在不改变现有对象结构下,动态的给对象添加一些功能

优缺点

优点

        1.装饰器是继承的有力补充,比继承灵活,在不改变原有对象的情况下,动态的给一个对象扩展功能,即插即用

        2.通过使用不用装饰类及这些装饰类的排列组合,可以实现不同效果

        3.装饰器模式完全遵守开闭原则

缺点

        装饰器模式会增加许多子类,过度使用会增加程序得复杂性

模式结构

角色:

        抽象构件角色:定义一个抽象接口以规范准备接收附加责任的对象

        具体构件角色:实现抽象构件,通过装饰角色为其添加一些职责

        抽象装饰角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能

        具体装饰角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任

结构图:

使用

1.创建接口

public interface Shape {  double getArea();  
}

2.接口具体实现类

public class Rectangle implements Shape {  private double length;  private double width;  public Rectangle(double length, double width) {  this.length = length;  this.width = width;  }  @Override  public double getArea() {  return length * width;  }  
}

3.创建抽象装饰器

public abstract class ShapeDecorator implements Shape {  protected Shape decoratedShape;  public ShapeDecorator(Shape shape) {  this.decoratedShape = shape;  }  @Override  public double getArea() {  return decoratedShape.getArea();  }  
}

4.创建具体装饰器

public class RectangleWithBorder extends ShapeDecorator {  private double borderWidth;  public RectangleWithBorder(Shape shape, double borderWidth) {  super(shape);  this.borderWidth = borderWidth;  }  @Override  public double getArea() {  return decoratedShape.getArea() + borderWidth * decoratedShape.getArea();  }  
}

5.使用

public class Main {  public static void main(String[] args) {  Shape rectangle = new Rectangle(5, 5);  Shape rectangleWithBorder = new RectangleWithBorder(rectangle, 1); // 给矩形添加边框宽度为1的装饰器  System.out.println("Rectangle area: " + rectangle.getArea()); // 输出:Rectangle area: 25.0  System.out.println("Rectangle with border area: " + rectangleWithBorder.getArea()); // 输出:Rectangle with border area: 27.0  }  
}

使用场景

1.扩展功能:当您想要扩展一个类的功能时,可以使用装饰器模式来添加新的责任,而不需要修改原有类的代码。这使得代码更加灵活,易于维护

2.动态变化:如果需要在运行时根据需要动态地改变对象的行为,可以使用装饰器模式

3.统一接口:如果有一组具有相似功能但是又不完全相同的类,可以使用装饰器模式来统一它们的接口,使得在使用它们时不需要关心具体的类

4.延迟加载:如果某些数据是可选的,可以在需要时才加载,使用装饰器模式可以实现延迟加载的功能

5.处理复杂对象:当涉及到复杂的对象结构时,装饰器模式可以简化代码。通过将不同的行为封装到不同的装饰器中,可以组合这些装饰器来创建具有不同行为的对象

        装饰器模式适用于在不修改原有代码的基础上,动态地给对象添加新的行为。它适用于需要在运行时动态地改变对象行为或者需要统一接口的场景。

相关文章:

设计模式之适配器与装饰器

目录 适配器模式 简介 角色 使用 优缺点 使用场景 装饰器模式 简介 优缺点 模式结构 使用 使用场景 适配器模式 简介 允许将不兼容的对象包装成一个适配器类,使得其他类可以通过适配器类与原始对象进行交互,从而提高兼容性 角色 目标角色…...

服务器数据恢复- Ext4文件系统分区挂载报错的数据恢复案例

Ext4文件系统相关概念: 块组:Ext4文件系统的空间被划分为若干个块组,每个块组内的结构大致相同。 块组描述符表:每个块组都对应一个块组描述符,这些块组描述符统一放在文件系统的前部,称为块组描述符表。每…...

19-springcloud(上)

一 微服务架构进化论 单体应用阶段 (夫妻摊位) 在互联网发展的初期,用户数量少,一般网站的流量也很少,但硬件成本较高。因此,一般的企业会将所有的功能都集成在一起开发一个单体应用,然后将该单体应用部署到一台服务器…...

前端基础---HTML笔记汇总一

HTML定义 HTML超文本标记语言——HyperText Markup Language。 超文本是什么&#xff1f; 链接标记是什么&#xff1f; 标记也叫标签&#xff0c;带尖括号的文本 标签分类 单标签:只有开始标签&#xff0c;没有结束标签(<br>换行 <hr>水平线 <img> 图像标…...

智汇云舟亮相中国安防工程商集成商大会

智汇云舟亮相中国安防工程商集成商大会&#xff0c;以视频孪生驱动安防行业数字化转型 近日&#xff0c;由中国安全防范产品行业协会指导&#xff0c;永泰传媒主办的中国安防工程商&#xff08;系统集成商&#xff09;大会暨第69届中国安防新产品、新技术成果展示在石家庄圆满…...

使用 Sealos 在离线环境中光速安装 K8s 集群

作者&#xff1a;尹珉。Sealos 开源社区 Ambassador&#xff0c;云原生爱好者。 当容器化交付遇上离线环境 在当今快节奏的软件交付环境中&#xff0c;容器化交付已经成为许多企业选择的首选技术手段。在可以访问公网的环境下&#xff0c;容器化交付不仅能够提高软件开发和交付…...

算法-模拟

1、旋转数组 public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可** 旋转数组* param n int整型 数组长度* param m int整型 右移距离* param a int整型一维数组 给定数组* return int整型一维数组*/…...

如何通过Instagram群发消息高效拓展客户?

之前小S有跟大家说过关于独立站&#xff0b;Instagram如何高效引流&#xff0c;发现大家都对Instagram的话题挺关注的。Instagram作为全球最受欢迎的社交媒体之一&#xff0c;对于许多商家和营销人员来说&#xff0c;Instagram是一个不可忽视的营销平台&#xff0c;他们可以通过…...

基于springboot实现多线程抢锁的demo

1、本代码基于定时调度和异步执行同时处理&#xff0c;如果只加异步处理&#xff0c;会导致当前任务未执行完&#xff0c;下个任务到点也不会触发执行 Scheduled(fixedRate 50_000)Asyncpublic void testThread() throws Exception{ZkLock lock new ZkLock(zkJob.getZK(), &q…...

Java I/O模型发展以及Netty网络模型的设计思想

Java I/O模型发展以及Netty网络模型的设计思想 I/O模型Java BIOJava NIOJava AIO NIO Reactor网络模型单Reactor单线程模型单Reactor多线程模型主从Reactor多线程模型 Netty通信框架 前言&#xff1a; BIO、NIO的代码实践参考&#xff1a;Java分别用BIO、NIO实现简单的客户端服…...

智能电网时代:数字孪生的崭露头角

随着科技的不断进步&#xff0c;数字孪生已经开始在电力行业崭露头角&#xff0c;为这个关键的行业带来了前所未有的机遇和潜力。本文就带大家了解一下数字孪生在哪些方面为电力行业做出改变&#xff0c;以及未来的创新应用。 首先&#xff0c;数字孪生可以提高电力系统运营效率…...

每日一题 501二叉搜素树中的众数(中序遍历)

题目 给你一个含重复值的二叉搜索树&#xff08;BST&#xff09;的根节点 root &#xff0c;找出并返回 BST 中的所有 众数&#xff08;即&#xff0c;出现频率最高的元素&#xff09;。 如果树中有不止一个众数&#xff0c;可以按 任意顺序 返回。 假定 BST 满足如下定义&a…...

测试理论与方法----测试流程第三个环节:设计测试用例

测试流程第三个环节&#xff1a;设计测试用例&#xff1a;怎么测<——>测试需求的提取&#xff1a;测什么 ### 5、测试用例 描述&#xff1a;测试用例(TestCase)&#xff1a;是一份关于【具体测试步骤】的文档&#xff0c;是为了达到最佳的测试效果或高效揭露软件中潜藏的…...

C++多态案例2----制作饮品

#include<iostream> using namespace std;//制作饮品的大致流程都为&#xff1a; //煮水-----冲泡-----倒入杯中----加入辅料//本案例利用多态技术&#xff0c;提供抽象类制作饮品基类&#xff0c;提供子类制作茶叶和咖啡class AbstractDrinking {public://煮水//冲水//倒…...

机械零件保养3d模拟演示打消客户购买顾虑

复杂机械的工作运转是复杂的&#xff0c;想要对机械有深度的理解和迭代&#xff0c;必须了解它的运转原理及参数&#xff0c;复杂机械运行原因教学存在着不可视、系统庞杂及知识点多等弊病&#xff0c;3D虚拟展示是基于web3d网页运行的三维页面&#xff0c;可以将复杂机械运行过…...

SpringBoot的自动装配源码分析

文章目录 一&#xff1a;什么是自动装配二、springboot的启动流程1.调用SpringApplication&#xff08;&#xff09;的构造方法2.执行核心run方法&#xff08;&#xff09;3.执行核心prepareContext&#xff08;&#xff09;4.执行核心refreshContext&#xff08;&#xff09;5…...

Linux常用命令——csplit命令

在线Linux命令查询工具 csplit 将一个大文件分割成小的碎片文件 补充说明 csplit命令用于将一个大文件分割成小的碎片&#xff0c;并且将分割后的每个碎片保存成一个文件。碎片文件的命名类似“xx00”&#xff0c;“xx01”。csplit命令是split的一个变体&#xff0c;split只…...

React 组件的3大属性: state

state 一、理解二、用途三、使用3.1、类初始化3.2、函数初始化 四、状态读更4.1、组件内部状态管理和数据更新4.2、state 和 props 一起使用 一、理解 组件被称为"状态机", 页面的显示是根据组件的state 属性的数据来显示。 state 是一个用于存储和管理组件内部数据的…...

vscode 上传项目到gitlab

第一步初始化项目 如果没有创建过分支&#xff08;创建分支这里不记录&#xff09;&#xff0c;默认是master分支&#xff1a; ①将所需要的上传的文件添加到暂存区&#xff0c;如图&#xff1a; ②填写一下注释信息&#xff0c;将暂存区的文件上传到本地分支&#xff08;没有创…...

[羊城杯 2020] easyphp

打开题目&#xff0c;源代码 <?php$files scandir(./); foreach($files as $file) {if(is_file($file)){if ($file ! "index.php") {unlink($file);}}}if(!isset($_GET[content]) || !isset($_GET[filename])) {highlight_file(__FILE__);die();}$content $_GE…...

QT 常用类与组件

0 思维导图 1 信息调试类&#xff08;QDebug&#xff09; #include "widget.h" #include<iostream> //printf #include<QDebug> //qDebuf using namespace std; //coutWidget::Widget(QWidget *parent): QWidget(parent) {//输出函数//使用…...

C#控制台连接Mysql数据库,有配置数据库连接字符串的配置文件

C#控制台连接Mysql数据库&#xff0c;有配置数据库连接字符串的配置文件 实现功能 读取..txt 中的配置文件&#xff0c;来初始化连接字符串让连接字符串的配置文件不存在会主动创建默认的连接字符串 注意点&#xff1a; 需要引用Newtonsoft使用mysql 代码如下 using Syst…...

PowerBuilder连接SQLITE3

PowerBuilder,一个古老的IDE,打算陆续发些相关的,也许还有人需要,内容可能涉及其他作者,但基本都是基于本人实践整理,如涉及归属,请联系. SQLite,轻型数据库,相对与PowerBuilder来说是个新事务,故发数来,以供参考. PB中使用OLE Microsoft OLE DB方式进行连接,如下 // Profile…...

Git 基本原理和常用操作

Git Git 是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的项目版本管理。由 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开源的版本控制软件。 Git 常用操作 git 提交流程&#xff1a;工作区 -> git add 到暂存区 -> gi…...

单元测试和集成测试的区别

单元测试和集成测试是软件开发中常用的两种测试方法&#xff0c;它们的主要区别如下&#xff1a; 范围不同&#xff1a;单元测试关注于对软件中的最小功能单元进行测试&#xff0c;通常是对独立的函数、方法或类进行测试。而集成测试则更加综合&#xff0c;涉及多个模块、组件或…...

node基础概念

前言&#xff1a;可以让别人访问我们的网页&#xff0c;可以开发服务端应用、工具类应用、桌面端应用&#xff08;electron&#xff09; 1. 计算机基础 概念&#xff1a;CPU 内存 硬盘 主板 显卡 2. 进程和线程 概念&#xff1a;进程是一个程序的执行&#xff0c;线程组合形…...

ArcGIS Maps SDK for JS(二):MapView简介----创建2D地图

文章目录 1 AMD 引用 ArcGIS Maps SDK for JavaScript2 加载相应模块3 创建地图4 创建 2D 视图 view5 确定页面内容6 CSS 样式7 完整代码 本教程使用 AMD 模块&#xff0c;指导您如何在二维地图视图中创建一个简单的地图。 1 AMD 引用 ArcGIS Maps SDK for JavaScript 在 <…...

知识图谱推理研究综述9.3

综述分类 根据样本量大小的不同&#xff0c;将知识图谱推理方法分为多样本推理、少样本推理和零与单样本推理 KG定义&#xff1a;&#xff08;Y&#xff09; 知识图谱是以图的形式表示真实世界的实体与关系之间关系的知识库。 具体来说知识图谱是通过将应用数学、图形学、信…...

详细介绍c++中的类

C 中的类是面向对象编程的基本概念&#xff0c;它指的是一种能够封装数据和方法的用户定义数据类型。类是程序中一个重要的概念&#xff0c;它允许程序员通过定义类来实现代码复用、模块化和继承等特性。 C 中的类由以下部分组成&#xff1a; Data members&#xff1a;成员变量…...

C语言:扫雷小游戏

文接上一篇博文C语言&#xff1a;三子棋小游戏。本篇博文是使用C语言来实现扫雷小游戏的。这里不对扫雷的规则进行赘述。玩家通过键盘输入坐标来探雷。博主在实现扫雷之前从未看过扫雷实现的相关视频&#xff0c;所以这里实现的扫雷完全是博主的原生思路&#xff0c;具有逻辑性…...