[设计模式Java实现附plantuml源码~结构型]不兼容结构的协调——适配器模式

前言:
为什么之前写过Golang 版的设计模式,还在重新写Java 版?
答:因为对于我而言,当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言,更适合用于学习设计模式。
为什么类图要附上uml
因为很多人学习有做笔记的习惯,如果单纯的只是放一张图片,那么学习者也只能复制一张图片,可复用性较低,附上uml,方便有新理解时,快速出新图。


🔥[设计模式Java实现附plantuml源码]专链

  1. 确保对象的唯一性~单例模式
  2. 集中式工厂的实现~简单工厂模式
  3. 多态工厂的实现——工厂方法模式
  4. 产品族的创建——抽象工厂模式
  5. 对象的克隆~原型模式
  6. 复杂对象的组装与创建——建造者模式
  7. 提供统一入口——外观模式
  8. 扩展系统功能——装饰模式
  9. 树形结构的处理——组合模式
  10. 对象的间接访问——代理模式
  11. 不兼容结构的协调——适配器模式

文章目录

    • 不兼容结构的协调——适配器模式
      • 简单代码实现
      • 扩展
        • 类适配器模式
        • 双向适配器模式
        • 缺省适配器模式
      • 适配器模式总结
        • 无论是对象适配器模式还是类适配器模式都具有如下优点:
        • 类适配器模式的缺点如下:
      • 适用场景


不兼容结构的协调——适配器模式

适配器模式可以将一个类的接口和另一个类的接口匹配起来,而无须修改原来的适配者接口和抽象目标类接口。适配器模式定义如下:适配器模式(Adapter Pattern):将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。注:在适配器模式定义中所提及的接口是指广义的接口,它可以表示一个方法或者一组方法的集合。

在这里插入图片描述

@startuml

class Client {}

class Target {
+ request()
}
class Adaptee {
+ specificRequest()
}
class Adapter {
- Adaptee adaptee;
+ request()
}

note left of Adapter::request 
adaptee.specificRequest()
end note

Client -right-> Target
Target --> Adapter
Adapter -right-> Adaptee



@end

在对象适配器模式结构图中包含以下3个角色。
(1)Target(目标抽象类):目标抽象类定义客户所需接口,可以是一个抽象类或接口,也可以是具体类。
(2)Adapter(适配器类):适配器可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配。适配器类是适配器模式的核心,在对象适配器模式中,它通过继承Target并关联一个Adaptee对象使二者产生联系。
(3)Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配。适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。

简单代码实现

package struct;

public class AdapterDemo {
    public static void main(String[] args) {
        new Adapter(new Adaptee()).request();

    }
    
    static class Adaptee {
        public void specificRequest() {
            System.out.println("adapte request");
        }
    }

    static class Adapter {
        private final Adaptee adaptee;
        public Adapter(Adaptee adaptee) {
            this.adaptee = adaptee;
        }

        public void request() {
            System.out.println("adapter request ");
            adaptee.specificRequest();
        }
    }
}

扩展

类适配器模式

除了对象适配器模式之外,适配器模式还有一种形式,那就是类适配器模式。类适配器模式与对象适配器模式最大的区别在于其适配器和适配者之间的关系是继承关系。类适配器模式结构如下所示。
在这里插入图片描述

@startuml

class Client {}

class Target {
+ request()
}
class Adaptee {
+ specificRequest()
}
class Adapter extends Adaptee{
+ request()
}

note left of Adapter::request 
super.specificRequest()
end note

Client -right-> Target
Target --> Adapter




@end
双向适配器模式

在对象适配器模式的使用过程中,如果在适配器中同时包含对目标类和适配者类的引用,适配者可以通过它调用目标类中的方法,目标类也可以通过它调用适配者类中的方法,那么该适配器就是一个双向适配器。其模式结构示意图如下所示。

在这里插入图片描述

@startuml

interface Target {
+ request()
}
interface Adaptee {
+ specificRequest()
}
class ConcreteTarget implements Target{
+ request()
}
class ConcreteAdaptee implements Adaptee {
+ specificRequest()
}
class Adapter implements Target, Adaptee {
- Adaptee adaptee;
- Target target;
+ Adapter(Target target)
+ Adapter(Adaptee adaptee)
+ request()
+ specificRequest()
}

note left of Adapter::request 
adaptee.specificRequest()
end note

note left of Adapter::specificRequest 
target.request
end note





@end
缺省适配器模式

缺省适配器模式是适配器模式的一种变体,其应用也较为广泛。
缺省适配器模式的定义如下:缺省适配器模式(Default Adapter Pattern):当不需要实现一个接口所提供的所有方法时,可先设计一个抽象类实现该接口,并为接口中每个方法提供一个默认实现(空方法),那么该抽象类的子类可以选择性地覆盖父类的某些方法来实现需求。它适用于不想使用一个接口中的所有方法的情况,又称为单接口适配器模式。

适配器模式总结

无论是对象适配器模式还是类适配器模式都具有如下优点:

(1)将目标类和适配者类解耦。通过引入一个适配器类来重用现有的适配者类,无须修改原有结构。
(2)增加了类的透明性和复用性。将具体的业务实现过程封装在适配者类中,对于客户端类而言是透明的,而且提高了适配者类的复用性,同一个适配者类可以在多个不同的系统中复用。
(3)灵活性和扩展性都非常好。通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合开闭原则。


具体来说,类适配器模式还有这样的优点:由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。
对象适配器模式还有如下优点:(1)一个对象适配器可以把多个不同的适配者适配到同一个目标。(2)可以适配一个适配者的子类。由于适配器和适配者之间是关联关系,根据里氏代换原则,适配者的子类也可通过该适配器进行适配。

类适配器模式的缺点如下:

(1)对于Java、C#等不支持多重类继承的语言,一次最多只能适配一个适配者类,不能同时适配多个适配者。
(2)适配者类不能为最终类,例如在Java中不能为final类,C#中不能为sealed类。
(3)在Java、C#等语言中,类适配器模式中的目标抽象类只能为接口,不能为类,其使用有一定的局限性。
对象适配器模式的缺点是:与类适配器模式相比,要在适配器中置换适配者类的某些方法比较麻烦。如果一定要置换掉适配者类的一个或多个方法,可以先做一个适配者类的子类,在子类中将适配者类的方法置换掉,然后再把适配者类的子类当作真正的适配者进行适配,实现过程较为复杂。

适用场景

在以下情况下可以考虑使用适配器模式:
(1)系统需要使用一些现有的类,而这些类的接口(例如方法名)不符合系统的需要,甚至没有这些类的源代码。
(2)想创建一个可以重复使用的类,用于与一些彼此之间没有太大关联的类,包括一些可能在将来引进的类一起工作。


🚀 作者简介:作为某云服务提供商的后端开发人员,我将在这里与大家简要分享一些实用的开发小技巧。在我的职业生涯中积累了丰富的经验,希望能通过这个博客与大家交流、学习和成长。技术栈:Java、Golang、PHP、Python、Vue、React


本文收录于三木的
💐 「设计模式」专栏
此外三木还有以下专栏在同步更新~

🌼 「AI」专栏

🔥「面试」这个专栏的灵感来自于许多粉丝私信,大家向我咨询有关面试的问题和建议。我深感荣幸和责任,希望通过这个专栏,能够为大家提供更多关于面试的知识、技巧和经验。我们将一起探讨面试。期待粉丝们ssp的offer喜讯。

🎈 「Java探索者之路」系列专栏,这个专栏旨在引领Java开发者踏上一段真正探索Java世界的旅程。
我们将深入探讨Java编程的方方面面,从基础知识到高级技巧,从实践案例到最新趋势,帮助你成为一名卓越的Java探索者。如果有想进入Java后端领域工作的同学,这个专栏会对你有所帮助,欢迎关注起来呀

🌊 「Python爬虫」的入门学习系列,大家有兴趣的可以看一看


🌹一起学习,互三互访,顺评论区有访必回,有关必回!!!


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PCB设计10条重要布线原则(学习笔记)

文章目录 一、连线精简二、避免走直角线三、差分走线四、蛇形走线五、圆滑走线六、数字与模拟分开七、3W原则八、20H原则九、铜箔承载电流十、过孔承载电流 一、连线精简 尽量用最短的路径去布线 1、可以省资源 2、信号差损少 3、线能不拐弯就不拐弯 4、能不换层就不换层 二…

MongoDB安装以及卸载,通过Navicat 15 for MongoDB连接MongoDB

查询id: docker ps [rootlocalhost ~]# docker stop c7a8c4ac9346 c7a8c4ac9346 [rootlocalhost ~]# docker rm c7a8c4ac9346 c7a8c4ac9346 [rootlocalhost ~]# docker rmi mongo sudo docker pull mongo:4.4 sudo docker images 卸载旧的 sudo docker stop mong…

Django4.2(DRF)+Vue3 读写分离项目部署上线

文章目录 1 前端2 后端2.1 修改 settings.py 文件关于静态文件2.2 关于用户上传的文件图片 3 Nginx4 镜像制作4.1 nginx4.3 Django镜像4.3.1 构建 5 docker-compose 文件内容 1 前端 进入前端项目的根目录,运行如下命令进行构建 npm run build构建完成后&#xff…

Apple Vision Pro 评测:这款顶尖头显仅是对未来的初步探索

原文:Apple Vision Pro Review: The Best Headset Yet Is Just a Glimpse of the Future 作者:Joanna Stern 戴上 Apple Vision Pro 混合现实头显整整近 24 小时后,有几件事让我颇感意外: 我居然没感到恶心。我竟然高效完成了大…

云纱网签约百望云,联手打造数字化产业闭环

近日,百望云签约广东云纱数字科技有限公司,共建数字化发票管理系统,赋能产业链上下游供应商的协同交易与运营,助力企业实现数字化四流合一交易,打造数字化产业闭环。 云纱网是广东云纱数字科技有限公司依托于深厚的产业…

利用牛顿方法求解非线性方程(MatLab)

一、算法原理 1. 牛顿方法的算法原理 牛顿方法(Newton’s Method),也称为牛顿-拉弗森方法,是一种用于数值求解非线性方程的迭代方法。其基本思想是通过不断迭代来逼近方程的根,具体原理如下: 输入&#…

STM32——DMA

STM32——DMA 1.DMA介绍 什么是DMA? DMA(Direct Memory Access,直接存储器访问) 提供在外设与内存、存储器和存储器、外设与外设之间的高速数据传输使用。它允许不同速度的硬件装置来沟通,而不需要依赖于CPU,在这个时间中&…

移动端设计规范 - 文字使用规范

这是一篇关于移动端产品界面设计时,文字大小的使用规范,前端人员如果能了解一点的话,在实际开发中和设计沟通时,节省沟通成本,也能提高设计落地开发时的还原度。 关于 在做移动端产品设计时,有时候使用文字…

fpmarkets实例讲解止损,控制风险如此简单

止损和止盈是交易者在交易时都需要了解的两个基本设置,在上篇文章fpmarkets澳福和各位投资者分享 了止盈如何工作,今天我们继续实例讲解止损,在交易中控制不必要的风险。 止损单是基本交易订单之一。如果市场走向与预期相反,它会限…

[机器学习]LFM梯度下降算法

一.LFM梯度下降算法 2.代码实现 # 0. 引入依赖 import numpy as np import pandas as pd# 1. 数据准备 # 评分矩阵R R np.array([[4,0,2,0,1],[0,2,3,0,0],[1,0,2,4,0],[5,0,0,3,1],[0,0,1,5,1],[0,3,2,4,1],]) # 二维数组小技巧:取行数R.shape[0]和len(R)&#x…

【SPIE独立出版|长春理工大学主办】2024年第四届数字信号与计算机通信国际学术会议(DSCC 2024)

DSCC 2024已通过SPIE出版社审核,ISSN号已确定:ISSN: 0277-786X,往届均已见刊EI检索! 2024年第四届数字信号与计算机通信国际学术会议(DSCC 2024) 2024 4th International Conference on Digital Signal and…

Windows Server 2025 Azure Arc 介绍

Azure Arc 是一个扩展 Azure 平台的桥梁,可帮助你构建可灵活地跨数据中心、边缘和多云环境运行的应用程序和服务。使用一致的开发、操作和安全模型来开发云原生应用程序。 Azure Arc 可在新的和现有的硬件、虚拟化和 Kubernetes 平台、物联网设备和集成系统上运行。…

Flutter 开发3:创建第一个Flutter应用

Step 1: 安装Flutter 1.1 下载Flutter SDK 首先,你需要访问Flutter官方网站下载最新的Flutter SDK。选择适合你操作系统的安装包。 $ cd ~/development $ unzip ~/Downloads/flutter_macos_2.2.3-stable.zip1.2 更新环境变量 接下来,你需要将Flutter…

【项目管理】整合管理

一、管理基础 1、项目整合管理由项目经理负责,项目经理负责整合所有其他知识领域的成果,并掌握项目总体情况。项目整合管理的责任不能被授权或转移,项目经理必须对整个项目承担最终责任。整合是项目经理的一项关键技能。执行项目整合时项目经…

西门子WINCC触摸屏的Audit功能:追溯生产数据与用户操作行为

1为什么要用Audit功能? 在许多工业领域,生产数据的可追溯性及其文档记录变得愈加重要,如医药行业、食品饮料以及相关的机械工程行业。与书面文档相比,以电子形式存储生产数据具有许多优点,如采集和记录数据更方便&…

【HarmonyOS】鸿蒙开发之页面路由——第2.4章

页面路由: 应用程序中实现不同页面之间的跳转和数据传递。 Router有两种页面跳转模式 1.router.pushUrl() 目标耶不会被替换当前页,而是压入页面栈,可以使用router.back()返回当前页 2.router.replaceUrl() 目标替换当前页,当前页会被销毁并…

一文读懂cookie、session和token

HTTP简介 HTTP协议(超文本传输协议HyperText Transfer Protocol)是一种无状态协议,协议本身不会对发送过的请求和对应的通信状态进行持久化处理。这样的好处是可以保持HTTP协议的简单性,高效率处理大量事务。 但是随之就会出现一…

代码随想录算法训练营第36天(贪心算法05 ● 435. 无重叠区间 ● 763.划分字母区间 ● 56. 合并区间

贪心算法 part05 435. 无重叠区间解题思路 763.划分字母区间解题思路补充 56. 合并区间解题思路不熟悉的基础语法知识 详细布置 今天的三道题目,都算是 重叠区间 问题,大家可以好好感受一下。 都属于那种看起来好复杂,但一看贪心解法&#x…

【C++入门到精通】特殊类的设计 | 单例模式 [ C++入门 ]

阅读导航 引言一、设计模式概念(了解)二、单例模式1. 饿汉模式(1)概念(2)模拟实现(3)优缺点(4)适用场景 2. 懒汉模式(1)概念&#xff…

vue使用富文本

1、安装 cnpm install vue-quill-editor2、在main.js中引入 // 富文本 import VueQuillEditor from vue-quill-editor // require styles 引入样式 import quill/dist/quill.core.css import quill/dist/quill.snow.css import quill/dist/quill.bubble.css Vue.use(VueQuill…