【设计模式】结构型设计模式之 适配器模式

news2024/11/8 20:32:31

介绍

适配器模式(Adapter Pattern) 是一种结构型设计模式,它的核心目的是使接口不兼容的类能够协同工作。适配器模式通过将一个类的接口转换为客户希望的另一个接口,来解决两个已有接口之间不匹配的问题,从而增加它们之间的兼容性。这种模式在需要复用现有类,而又不想修改原有接口或者无法修改原有接口的情况下特别有用。

适配器模式关键角色

  1. 目标(Target):这是客户所期待的接口,也是适配器转换后需要符合的接口。客户代码通过这个接口与适配器交互。
  2. 适配者(Adaptee):这是需要被适配的类或接口,拥有特定的接口,但是不符合客户的需求。
  3. 适配器(Adapter):这个类负责将适配者的接口转换为客户所期待的目标接口。它通过继承或组合的方式来包装适配者,同时实现目标接口,使得原本不兼容的接口可以协同工作。

适配器模式的种类

  1. 对象适配器(Object Adapter):在这种方式中,适配器包含一个对适配者类的引用,通过委托调用适配者的方法来达到适配的目的。这种方式更加灵活,因为适配器和适配者之间是松耦合的。
  2. 类适配器(Class Adapter):在这种方式中,适配器继承自适配者类,并实现目标接口。由于Java等语言不支持多重继承,这种模式的使用可能会受到限制,且它使得适配器和适配者之间是紧耦合的。

对象适配器和类适配器

类适配器 -基于继承

//适配的目标
public interface ITarget{
    void f1();
    void f2();
    void fc();
}

//需要被适配的类
public class Adaptee{
    public void fa(){...}
    public void fb(){...}
    public void fc(){...}
}

//适配器类
public class Adaptor extends Adaptee implements ITarget{
    //将fa适配到f1中
    public void f1(){
        super.fa();
    }

    public void f2(){
        //自定义重新实现f2
    }

    //fc不用实现,可以直接复用。这是和对象适配器最大的不同
}

对象适配器-基于组合

//适配的目标
public interface ITarget{
    void f1();
    void f2();
    void fc();
}

//需要被适配的类
public class Adaptee{
    public void fa(){...}
    public void fb(){...}
    public void fc(){...}
}

public class Adaptor implements ITarget{
    private Adaptee adaptee;
    //组合被适配的类
    public Adaptor(Adaptee adaptee){
        this.adaptee=adaptee;
    }

    //委托给adaptee实现
    public void f1(){
        adaptee.fa();
    }

    public void f2(){
        //自定义重新实现f2
    }

    //委托给adaptee实现
    public void fc(){
        adaptee.fc();
    }
    
}

如何确定使用继承还是组合

  1. 如果 Adaptee 方法并不多,那么两种方法都可以。
  2. 如果 Adaptee 的方法很多,但是大部分和 Target 相同,那么推荐使用继承。这样可以减少编码数量
  3. 如果 Adaptee 的方法很多,但是定义和 Target 不相同,那么推荐使用组合更加的灵活。

适配器模式的五种应用场景

  1. 封装有缺陷的接口设计:假设外部类包含很多不需要的静态方法,那么可以使用适配器模式对其进行重新封装得到更易用、更易测试的接口。
  2. 统一多个同种功能的类的接口设计 例如使用多个敏感词过滤系统过滤敏感词,对不同的敏感词系统的 API 适配成统一的接口设计。后续只需要对敏感词系统的接口进行依次遍历,就算接口有变动也只需要修改过滤器。而不涉及具体的客户端代码。
  3. **替换依赖的外部系统 **如果需要将系统 A 的系统替换成另一个外部系统,适配器模式可以减少对代码的改动。对于接口 A 系统 IA 替换成系统 B 时,创建 B 对A 的适配器,适配成 A 后替换原本使用 IA 的地方即可。
  4. 兼容老版本接口 对于老版本的功能接口,升级后可能有更优的实现。但是如果直接删除则会导致老项目无法正常运行,这时将新版本中的老接口的实现改为组合新对象的适配器实现则可以避免强制升级,又能享受新版本实现带来的好处。

适配器模式在 Java 日志系统中的应用


上图是目前 JAVA 目前各个日志系统的示意图,可以看到桥接包的数量比日志产品和日志门面接口还多。
JAVA 日志系统中由于没有统一的接口,导致各个日志系统互不兼容。后续推出了日志系统的接口后,各个厂家就纷纷对日志产品退出自己的桥接包。这真是应了那句经典理论“没有什么问题是加一层抽象层解决不了的,如果有就再加一层”

总结

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

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

相关文章

【Vue】声明式导航-自定义类名(了解)

问题 router-link的两个高亮类名 太长了,我们希望能定制怎么办 解决方案 我们可以在创建路由对象时,额外配置两个配置项即可。 linkActiveClass和linkExactActiveClass const router new VueRouter({routes: [...],linkActiveClass: "类名1&quo…

微信小程序毕业设计-网吧在线选座系统项目开发实战(附源码+论文)

大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。 💞当前专栏:微信小程序毕业设计 精彩专栏推荐👇🏻👇🏻👇🏻 🎀 Python毕业设计…

Hadoop 2.0:主流开源云架构(一)

目录 一、引例(一)问题概述(二)常规解决方案(三)分布式下的解决方案(四)小结 自从云计算的概念被提出,不断地有IT厂商推出自己的云计算平台,但它们都是商业性…

LeetCode | 997.找到小镇的法官

这道题拿到后很明显是一个图论的简单出度入度问题,法官的标志就是图中出度为0,入度为n-1的结点,而且根据题目条件,满足这一条件的结点有且只有一个 但是我不知道力扣中关于图论的邻接表和邻接矩阵这些数据结构是需要自己写还是已经…

shell编程(三)—— 控制语句

程序的运行除了顺序运行外,还可以通过控制语句来改变执行顺序。本文介绍bash的控制语句用法。 一、条件语句 Bash 中的条件语句让我们可以决定一个操作是否被执行。结果取决于一个包在[[ ]]里的表达式。 bash中的检测命令由[[]]包起来,用于检测一个条…

论文中eps格式图片制作

在提交论文终稿时,有时需要提交论文中图片的eps格式,这里记录一下eps格式图片制作的过程,方便以后查阅。 论文中eps格式图片制作 PPT绘制的图片转换为eps格式使用代码生成的图片Latex中显示的图片大小跟Ai中设定画板的大小不一致 PPT绘制的图…

品牌策划:不只是工作,是一场创意与学习的旅程

你是否认为只有那些经验丰富、手握无数成功案例的高手才能在品牌策划界崭露头角? 今天,我要悄悄告诉你一个行业内的秘密:在品牌策划的世界里,经验虽重要,但绝非唯一。 1️、无止境的学习欲望 品牌策划,这…

智能投顾:重塑金融理财市场,引领行业新潮流

一、引言 在数字化浪潮的推动下,金融行业正经历着前所未有的变革。其中,智能投顾作为金融科技的重要分支,以其高效、便捷和个性化的服务,逐渐成为金融理财市场的新宠。本文旨在探讨智能投顾如何引领金融理财新潮流,通过丰富的案例及解决方案,展示其独特的魅力和价值。 二…

Clearedge3d EdgeWise 5.8 强大的自动化建模软件

EdgeWise是功能强大的建模软件,提供领先的建模功能和先进的技术,让您的整个过程更快更准确!您可以获得使用自动特征提取和对象识别的 3D 建模,ClearEdge3D 自动建模和对象识别软件通过创建竣工文档和施工验证完成该过程。拓普康和…

Go singlefight 源码详解|图解

写在前面 通俗的来说就是 singleflight 将相同的并发请求合并成一个请求,进而减少对下层服务的压力,通常用于解决缓存击穿的问题。 详解 基础结构 golang.org/x/sync/singleflight singleflight结构体: type call struct {wg sync.WaitGro…

永磁同步电机双矢量模型预测转矩控制MPTC

导读:本期文章主要介绍永磁同步电机双矢量模型预测转矩控制。由于传统直接转矩控制和单矢量的模型预测转矩控制转矩纹波较大,且在全速范围内的开关频率不固定,针对这一缺陷,引入双矢量MPTC。 如果需要文章中的仿真模型&#xff0…

AI生成个性化壁纸

使用天工AI 将图片设置成桌面壁纸

transformer 位置编码源码解读

import torch import mathdef get_positional_encoding(max_len, d_model):"""计算位置编码参数:max_len -- 序列的最大长度d_model -- 位置编码的维度返回:一个形状为 (max_len, d_model) 的位置编码张量"""positional_e…

IDEA启动项目报java.lang.OutOfMemoryError: GC overhead limit exceeded

idea编译项目时报j ava.lang.OutOfMemoryError: GC overhead limit exceeded错误,教你两步搞定! 第一步:打开help -> Edit Custom VM Options ,修改xms和xmx的大小,如下图: 第二步:File -> Settings…

素数的无穷大的证明

素数的无穷大——欧几里得的证明 文章目录 一、说明二、欧几里得证据三、哥德巴赫对素数无穷性的证明(1730)四、Frstenberg 对素数无穷性的证明(1955)五、库默尔对欧几里得证明的重述 一、说明 众所周知,素数是无限多的。然而,两…

使用 Sysbench 测试文件的读写速度

要使用 Sysbench 测试文件的读写速度,你可以按照以下步骤进行: 安装 Sysbench: 如果你还没有安装 Sysbench,可以通过以下命令在 Ubuntu 上安装: sudo apt install sysbench创建测试文件: 首先&#xff0c…

32-读取Excel数据(xlrd)

本篇介绍如何使在python中读取excel数据。 一、环境准备 先安装xlrd模块,打开cmd,输入 pip install xlrd 在线安装。 二、基本操作 import xlrd# 打开excel表格 data xlrd.open_workbook(test.xlsx)# 2.获取sheet表格 # 方式一:通过索引顺…

【Java基础】多线程开发

Java多线程编程学习笔记 Author: Jim.kk Video: Bilibili 文章目录 Java多线程编程学习笔记学习路线简介程序、进程与线程的关系JVM简介 | 多线程在JVM中的执行示例CPU 线程的调度方式多线程的意义并行与并发 创建多线程 1 | Thread 与 Runnable方式 1 | 继承 Thread 类方式 …

spool 管道 小文件 mknod

Spool File In SQL*PLUS in Multiple Small Files ? (Doc ID 2152654.1)​编辑To Bottom In this Document Goal Solution APPLIES TO: Oracle Database - Enterprise Edition - Version 10.2.0.1 to 12.1.0.2 [Release 10.2 to 12.1] Oracle Database Cloud Schema Service…

【机器学习】基于卷积LSTM的视频预测

1. 引言 1.1 LSTM是什么 LSTM(Long Short-Term Memory)是一种特殊的循环神经网络(RNN)变体,旨在解决传统RNN在处理长序列数据时遇到的梯度消失和梯度爆炸问题。LSTM通过引入门控机制和细胞状态的概念,使得…