适配器设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。

在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 !

目录

1.适配器模式 2.抢救适配器 3.解决问题 4.类适配器 5.何时使用适配器模式 6.下载源代码

1.适配器模式

Max的软件开发人员已在一个电子商务网站上工作。 该网站允许用户在线购物和付款。 该站点与第三方支付网关集成在一起,用户可以通过该网关使用信用卡支付账单。 一切进展顺利,直到他的经理打电话给他要求更改项目。

经理告诉他,他们正计划更改支付网关供应商,他必须在代码中实现这一点。

这里出现的问题是该站点连接到采用Xpay类型对象的Xpay支付网关。 新的供应商PayD仅允许对象的PayD类型允许该过程。 Max不想更改引用了XPay类型对象的100个类的整个集合。 这也增加了已经在生产中运行的项目的风险。 他都不能更改支付网关的第三方工具。 由于代码的两个不同部分之间的接口不兼容,导致出现了问题。 为了使过程正常进行,Max需要找到一种使代码与供应商提供的API兼容的方法。

Xpay API的当前代码

图1

图1

现在,当前代码接口与新供应商的接口不兼容。

图2

图2

2.抢救适配器

Max在这里需要的是一个适配器,它可以位于代码和供应商的API之间,并可以使流程顺畅进行。 但是在解决方案之前,让我们首先了解一下适配器是什么以及它如何工作。

有时,可能会出现两个对象无法放在一起的情况,因为它们应该按顺序完成工作。 当我们尝试将旧代码与新代码集成在一起时,或在代码中更改第三方API时,可能会出现这种情况。 这是由于两个对象的接口不兼容而导致的。

适配器模式使您可以使对象或类公开的内容适应另一个对象或类期望的内容。 它将类的接口转换为客户端期望的另一个接口。 它允许类因接口不兼容而无法一起工作。 它允许修复对象和类之间的接口,而无需直接修改对象和类。

您可以将适配器视为真实世界的适配器,该适配器用于连接无法直接连接的两个不同的设备。 适配器位于这些设备之间,它从设备中获取流量并将其以所需的形式提供给其他设备,否则由于接口不兼容而无法获得。

适配器使用合成来存储应该适应的对象,并在调用适配器的方法时,将这些调用转换为适应的对象可以理解的内容,并将这些调用传递给适应的对象。 调用适配器的代码永远不需要知道它不是在处理它认为的对象类型,而是在处理对象。

图3

图3

现在,让我们看看如何解决Max的问题​​。

3.解决问题

当前,该代码公开给Xpay接口。 该界面如下所示:

package com.javacodegeeks.patterns.adapterpattern.xpay;public interface Xpay {public String getCreditCardNo();public String getCustomerName();public String getCardExpMonth();public String getCardExpYear();public Short getCardCVVNo();public Double getAmount();public void setCreditCardNo(String creditCardNo);public void setCustomerName(String customerName);public void setCardExpMonth(String cardExpMonth);public void setCardExpYear(String cardExpYear);public void setCardCVVNo(Short cardCVVNo);public void setAmount(Double amount);}

它包含一组setter和getter方法,用于获取有关信用卡和客户名称的信息。 此Xpay接口在用于实例化此类型对象的代码中实现,并将该对象暴露给供应商的API。

下列类定义了Xpay接口的实现。

package com.javacodegeeks.patterns.adapterpattern.site;import com.javacodegeeks.patterns.adapterpattern.xpay.Xpay;public class XpayImpl implements Xpay{private String creditCardNo;private String customerName;private String cardExpMonth;private String cardExpYear;private Short cardCVVNo;private Double amount;@Overridepublic String getCreditCardNo() {return creditCardNo;}@Overridepublic String getCustomerName() {return customerName;}@Overridepublic String getCardExpMonth() {return cardExpMonth;}@Overridepublic String getCardExpYear() {return cardExpYear;}@Overridepublic Short getCardCVVNo() {return cardCVVNo;}@Overridepublic Double getAmount() {return amount;}@Overridepublic void setCreditCardNo(String creditCardNo) {this.creditCardNo = creditCardNo;}@Overridepublic void setCustomerName(String customerName) {this.customerName = customerName;}@Overridepublic void setCardExpMonth(String cardExpMonth) {this.cardExpMonth = cardExpMonth;}@Overridepublic void setCardExpYear(String cardExpYear) {this.cardExpYear = cardExpYear;}@Overridepublic void setCardCVVNo(Short cardCVVNo) {this.cardCVVNo = cardCVVNo;}@Overridepublic void setAmount(Double amount) {this.amount = amount;}}

新供应商的关键界面如下所示:

package com.javacodegeeks.patterns.adapterpattern.payd;public interface PayD {public String getCustCardNo();public String getCardOwnerName();public String getCardExpMonthDate();public Integer getCVVNo();public Double getTotalAmount();public void setCustCardNo(String custCardNo);public void setCardOwnerName(String cardOwnerName);public void setCardExpMonthDate(String cardExpMonthDate);public void setCVVNo(Integer cVVNo);public void setTotalAmount(Double totalAmount);
}

如您所见,此接口具有一组需要在代码中实现的不同方法。 但是Xpay是由大部分代码创建的,更改整个类集确实非常困难且冒险。

我们需要某种方法,该方法能够满足供应商的要求,以便处理付款并在当前代码中进行很少甚至没有更改。 该方式由适配器模式提供。

我们将创建一个类型为PayD的适配器,它包装一个Xpay对象(它应该被适配的类型)。

package com.javacodegeeks.patterns.adapterpattern.site;import com.javacodegeeks.patterns.adapterpattern.payd.PayD;
import com.javacodegeeks.patterns.adapterpattern.xpay.Xpay;public class XpayToPayDAdapter implements PayD{private String custCardNo;private String cardOwnerName;private String cardExpMonthDate;private Integer cVVNo;private Double totalAmount;private final Xpay xpay;public XpayToPayDAdapter(Xpay xpay){this.xpay = xpay;setProp();}@Overridepublic String getCustCardNo() {return custCardNo;}@Overridepublic String getCardOwnerName() {return cardOwnerName;}@Overridepublic String getCardExpMonthDate() {return cardExpMonthDate;}@Overridepublic Integer getCVVNo() {return cVVNo;}@Overridepublic Double getTotalAmount() {return totalAmount;}@Overridepublic void setCustCardNo(String custCardNo) {this.custCardNo = custCardNo;}@Overridepublic void setCardOwnerName(String cardOwnerName) {this.cardOwnerName = cardOwnerName;}@Overridepublic void setCardExpMonthDate(String cardExpMonthDate) {this.cardExpMonthDate = cardExpMonthDate;}@Overridepublic void setCVVNo(Integer cVVNo) {this.cVVNo = cVVNo;}@Overridepublic void setTotalAmount(Double totalAmount) {this.totalAmount = totalAmount;}private void setProp(){setCardOwnerName(this.xpay.getCustomerName());setCustCardNo(this.xpay.getCreditCardNo());setCardExpMonthDate(this.xpay.getCardExpMonth()+"/"+this.xpay.getCardExpYear());setCVVNo(this.xpay.getCardCVVNo().intValue());setTotalAmount(this.xpay.getAmount());}}

在上面的代码中,我们创建了一个Adapter( XpayToPayDAdapter )。 适配器实现了PayD接口,因为需要像PayD类型的对象一样进行模拟。 适配器使用对象合成来保存对象(应该是自适应的),该对象是Xpay类型的对象。 该对象通过其构造函数传递到适配器中。

现在,请注意,我们有两种不兼容的接口类型,为了使代码正常工作,我们需要使用适配器将它们配合在一起。 这两个接口具有一组不同的方法。 但是,这些接口的唯一用途非常相似,即向其特定供应商提供客户和信用卡信息。

上一类的setProp()方法用于将xpay的属性设置为payD的对象。 我们在两个界面中设置工作方式相似的方法。 但是,只有在PAYD接口单一方法来设置月份和信用卡的一年,而在这两种方法Xpay接口。 我们加入了Xpay对象的两种方法( this.xpay.getCardExpMonth()+"/"+this.xpay.getCardExpYear() )的结果,并将其设置为setCardExpMonthDate()方法。

让我们测试上面的代码,看看它是否可以解决Max的问题​​。

package com.javacodegeeks.patterns.adapterpattern.site;import com.javacodegeeks.patterns.adapterpattern.payd.PayD;
import com.javacodegeeks.patterns.adapterpattern.xpay.Xpay;public class RunAdapterExample {public static void main(String[] args) {// Object for XpayXpay xpay = new XpayImpl();xpay.setCreditCardNo("4789565874102365");xpay.setCustomerName("Max Warner");xpay.setCardExpMonth("09");xpay.setCardExpYear("25");xpay.setCardCVVNo((short)235);xpay.setAmount(2565.23);PayD payD = new XpayToPayDAdapter(xpay);testPayD(payD);}private static void testPayD(PayD payD){System.out.println(payD.getCardOwnerName());System.out.println(payD.getCustCardNo());System.out.println(payD.getCardExpMonthDate());System.out.println(payD.getCVVNo());System.out.println(payD.getTotalAmount());}
}

在上面的类中,首先我们创建了一个Xpay对象并设置了它的属性。 然后,我们创建了一个适配器,并将该xpay对象传递给它的构造函数,并将其分配给PayD接口。 testPayD()静态方法采用PayD类型作为参数,该参数运行并打印其方法以进行测试。 就传递给testPayD()方法的类型为PayD类型PayD该方法将PayD执行对象。 上面,我们给它传递了一个适配器,它看起来像是PayD的类型,但是在内部它包装了Xpay类型的对象。

因此,在Max的项目中,我们需要在代码中实现供应商的API,并将此适配器传递给供应商的方法以使付款工作正常。 我们不需要更改现有代码中的任何内容。

图4

图4

4.类适配器

适配器有两种类型,对象适配器和类适配器。 到目前为止,我们已经看到了使用对象组成的对象适配器的示例,而类适配器则依靠多重继承来使一个接口适应另一个接口。 由于Java不支持多重继承,因此我们无法向您展示多重继承的示例,但是您可以牢记这一点,并可以用您喜欢的支持多种继承的面向对象语言(如c ++)之一来实现。

为了实现类适配器,适配器将从Target公开继承,并从Adaptee私有继承。 结果,适配器将是Target的子类型,但不是Adaptee的子类型。

图5

图5

5.何时使用适配器模式

在以下情况下应使用适配器模式:

  1. 有一个现有的类,并且其接口与您需要的接口不匹配。
  2. 您想创建一个可重用的类,与不相关或无法预料的类配合使用,即,不一定具有兼容接口的类。
  3. 现有多个子类可以使用,但是通过对每个子类进行子类化来调整其接口是不切实际的。 对象适配器可以调整其父类的接口。

6.下载源代码

这是有关适配器模式的课程。 您可以在此处下载源代码: AdapterPattern-Project

翻译自: https://www.javacodegeeks.com/2015/09/adapter-design-pattern.html

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

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

相关文章

cesium鼠标控制键盘_Cesium中级教程3 - Camera - 相机(摄像机)

CameraCesiumJS中的Camera控制场景的视图。有很多方法可以操作Camera,如旋转(rotate)、缩放(zoom)、平移(pan)和飞到目的地(flyTo)。CesiumJS有鼠标和触摸事件用来处理与Camrea的交互,还有API来以编程方式操作摄像机。了解如何使用Camera API和自定义相机…

windows下统一mysql编码_mysql5.7 windows7编码统一utf-8

查看mysql数据编码登录mysql服务,查看mysql数据库默认的编码mysql> show variables like character%;---------------------------------------------------------------------------| Variable_name | Value |------------------------------------------------…

python读取配置文件失败原因_python读取配置文件报keyerror-文件路径不正确导致的错误...

- 在其他模块使用反射读取配置文件报错,但是在反射模块中读取GetData.check_list又是正确的反射模块如下:# get_data.pyfrom API_AUTO.p2p_project_7.tools import project_pathimport pandas as pdfrom API_AUTO.p2p_project_7.tools.read_config impor…

备忘录设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 ! 目录 …

打印机一直显示正在删除不掉怎么办?

1、停止打印服务,按WinR键打开运行对话框,然后输入“services.msc ” 打开任务管理。 找到“Print Spooler”,先停止该服务。 按WinR键打开运行对话框,然后输入“Spool” 回车打开“spool” 文件夹,打开“PRINTERS”文…

java 并发 面试_Java 并发基础常见面试题总结

1. 什么是线程和进程?1.1. 何为进程?进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。在 Java 中,当我们启动 main 函数时其实就是启动了一个 JVM…

javafx动画_JavaFX:创建Sprite动画

javafx动画到目前为止,尽管我的大多数文章都涉及JavaFX属性和绑定,但是今天我想写一讲我也致力于JavaFX运行时的另一部分:动画API。 在本文中,我将解释如何在JavaFX中编写自定义动画,以及如何使用这种方法为Sprite动画…

FZU Problem 2238 Daxia Wzc's problem

Daxia在2016年5月期间去瑞士度蜜月,顺便拜访了Wzc,Wzc给他出了一个问题: Wzc给Daxia等差数列A(0),告诉Daxia首项a和公差d; 首先让Daxia求出数列A(0)前n项和,得到新数列A(1); 然后让Daxia求出数列A(1)前n项和,得到新数列A(2); 接着让Daxia求出数列A(2)前n项和,得到新…

生成器设计模式示例

本文是我们名为“ Java设计模式 ”的学院课程的一部分。 在本课程中,您将深入研究大量的设计模式,并了解如何在Java中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 ! 目录 …

【转】从 ArcGIS for Desktop 发布地图服务

原文链接:http://resources.arcgis.com/zh-CN/help/tutorials/01z300000007000000.htm 本教程的目的是将地图服务直接从 ArcGIS for Desktop 发布到 ArcGIS for Server 中。本教程与名为“在 ArcMap 中准备您的 Web 地图”的上一教程类似,需要使用 ArcGI…

java 模块化osgi_OSGi简介–模块化Java

java 模块化osgiOSGi联盟是这种搁浅的管理机构,它始于1999年。其最初目标是为网络设备创建开放搁浅。 基于此思想,此规范也针对Java引入。 Eclipse在Java中是第一个。 他们于2004年6月推出了基于OSGi的Eclipse IDE。 OSGi是在Java中定义动态模块的方法。…

Train Problem I hdu 1022(栈)

http://acm.split.hdu.edu.cn/showproblem.php?pid1022 题意&#xff1a;给出火车的进站与出站顺序&#xff0c;判断是否可以按照给出的出站顺序出站。 #include <iostream> #include <stdio.h> #include <string.h> #include <string> #include <…

Spring数据和Redis

本文是我们学院课程的一部分&#xff0c;标题为Redis NoSQL键值存储 。 这是Redis的速成班。 您将学习如何安装Redis并启动服务器。 此外&#xff0c;您将在Redis命令行中乱七八糟。 接下来是更高级的主题&#xff0c;例如复制&#xff0c;分片和集群&#xff0c;同时还介绍了…

史上最全的SpringMVC学习笔记

SpringMVC学习笔记---- 一、SpringMVC基础入门&#xff0c;创建一个HelloWorld程序 1.首先&#xff0c;导入SpringMVC需要的jar包。 2.添加Web.xml配置文件中关于SpringMVC的配置<!--configure the setting of springmvcDispatcherServlet and configure the mapping-->&…

shader weaver_Oracle通过邀请Weaver和Chin推动JavaFX向前发展

shader weaver昨天&#xff0c;我发布了愚人节帖子&#xff0c;内容涉及加入NASA协助探索红色大行星。 那篇文章与事实相距不远……美国宇航局开发的技术的所有细节都是100&#xff05;准确的。 哎呀&#xff0c;即使我辞职也是事实&#xff01; 唯一不正确的部分是我将加入的公…

mysql快速上手3

上一章给大家说的是数据库的视图&#xff0c;存储过程等等操作&#xff0c;这章主要讲索引&#xff0c;以及索引注意事项&#xff0c;如果想看前面的文章&#xff0c;url如下&#xff1a; mysql快速上手1mysql快速上手2索引简介 索引是对数据库表中一个或多个列&#xff08;例如…

python图像锐化_Python图像处理介绍--图像模糊与锐化

欢迎关注 “小白玩转Python”&#xff0c;发现更多 “有趣”引言在之前的文章中&#xff0c;我们讨论了边缘检测内核。在本文我们将讨论如何在图像上应用模糊与锐化内核&#xff0c;将这些内核应用到彩色图像上&#xff0c;同时保留核心图像。一如既往&#xff0c;我们从导入所…

Eclipse配置初始化(自用)

以上都是性能调优的配置&#xff0c;下面是其他常用的配置和优化 设置utf-8编码 window -> preferences -> General -> workplace中text file encoding改为utf-8 设置properties文件编码window -> preferences -> General -> Content Types —> Text —&g…

java bits_一段关于JAVA程序升级的问题(Changing bits)

展开全部import java.awt.Color;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.BorderFactory;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JTextField;import javax.…

java合并两个有序链表_JS实现的合并两个有序链表算法示例

本文实例讲述了JS实现的合并两个有序链表算法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。示例&#xff1a;输入&#xff1a;1->2->4, 1->3->4输出&…