设计模式适配器模式_适配器设计模式示例

设计模式适配器模式

本文是我们名为“ 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/336920.shtml

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

相关文章

mysql mgr bug_Mysql MGR架构误操作引发的问题处理

【背景介绍】故障方描述:一次用户刷权限的时候不小心把数据库用户表记录删掉了,执行之后发现不对后重建用户,杀掉进程后重新MGR启动报错。【报错信息】2018-06-13T12:47:41.405593Z 32 [Note] Plugin group_replication reported: Group comm…

css外墙法_外墙设计模式示例

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

设计模式示例_桥梁设计模式示例

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

数值分析 使用c语言 源码_分析源码,学会正确使用 Java 线程池

在日常的开发工作当中,线程池往往承载着一个应用中最重要的业务逻辑,因此我们有必要更多地去关注线程池的执行情况,包括异常的处理和分析等。本文主要聚焦在如何正确使用线程池上,以及提供一些实用的建议。文中会稍微涉及到一些线…

设计模式示例_状态设计模式示例

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

cam350 不能打开光绘文件_如何在CAM350中导入Allegro光绘

内容简介:本人之前遇到过 CAM350 导入 Allegro 格式光绘后钻孔偏移、异型孔不显示的问题,捣鼓过之后找到一个方法,在 Allegro 群友的建议下制作该文档进行适当的说明。1. 导入 Gerber 文件鉴于手工导入 Gerber 文件需要逐层设置,过…

d3js mysql_D3.js入门指南

近期略有点诸事不顺,趁略有闲余之时,玩起D3.js。之前实际项目中主要是用各种chart如hightchart、echarts等,这些图形库玩起来貌都是完美的,一切皆可配置,但几年前接触了D3之后,觉得前面那chart类库局限的地…

layui templet格式化_layui使用templet格式化表格数据的方法

增加js/*---------------------格式化时间开始--------------------------*///对Date的扩展,将 Date 转化为指定格式的String//月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符,//年(y)可以用 1-4 个占位符,毫秒(S)只能用…

设计模式示例_代理设计模式示例

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

mysql insert 字符集_有关 MySQL 字符集的注意事项-爱可生

本文关键字:字符集、建库建表一、数据库和字符集1. 建库时指定创建数据库时,显式指定字符集和排序规则,同时,当切换到当前数据库后,参数 character_set_database,collation_database 分别被覆盖为当前显式指…

c#发送讯息_企业讯息

c#发送讯息本文是我们名为“ EAI的Spring集成 ”的学院课程的一部分。 在本课程中,向您介绍了企业应用程序集成模式以及Spring Integration如何解决它们。 接下来,您将深入研究Spring Integration的基础知识,例如通道,转换器和适…

java cr_WildFly 10 CR 2发布– Java EE 7,Java 8,Hibernate 5,JavaScript支持热重载

java cr昨天,WildFly团队发布了最新版本的WildFly 10 。 CR2很可能是预计于十月份发布最终版本之前的最后一个版本。 即使主要支持的Java EE规范是7,WildFly 8和WildFly 9也提供了许多新功能,而WildFly 9和WildFly 9现在制作了三个服务器版本…

侬娜·杰尔_杰尔·地狱

侬娜杰尔什么是JAR地狱? (或者是classpath地狱?还是依赖地狱?)在考虑使用Maven或OSGi等现代开发工具时,哪些方面仍然有意义? 有趣的是,似乎没有对这些问题的结构化答案(…

Mysql运行在内核空间_思考mysql内核之初级系列6—innodb文件管理 | 学步园

在上一篇里面,bingxi和alex思考了information_schema,这个一直在innodb外围打转。没有进入到innodb的内部。在后续的文章中,以innodb的为主,逐个思考。Bingxi和alex今天了解了fil文件管理。对应的文件为:D:/mysql-5.1.…

pcl_openmap_OpenMap教程第2部分–使用MapHandler构建基本地图应用程序–第1部分

pcl_openmap1.简介 在第一个教程中,我们创建了一个基本的OpenMap GIS应用程序,该应用程序在JFrame中显示一个从文件系统加载的具有一个形状图层的地图。 该教程基于com.bbn.openmap.app.example.SimpleMap 。 在该教程中,我们使用了以下OpenM…

mysql7.5安装教程_CentOS7.5下yum安装MySQL8图文教程

卸载MariaDB1.列出所有安装的MariaDB rpm 包rpm -qa | grep mariadb2.强制卸载rpm -e --nodeps mariadb-libs-5.5.60-1.el7_5.x86_64安装MySQL1. 环境CentOS7.52. 获取MySQL最新版 rpm包yum仓库下载MySQLyum localinstall https://repo.mysql.com//mysql80-community-release-e…

mysql和sqlserver分页的区别_关于SQLServer和MySQL 查询分页语句区别

首先来定义几个要用到的参数(例子)t_user数据表int currentPage ; //当前页int pageRecord ; //每页显示记录数关于SqlServer数据库分页SQL语句为:String sql "select top "pageRecord " * from t_user where id not in (select top "(currentPage-1)*pag…

java 微型数据库_Java 9代码工具:使用Java微型基准测试工具的实践会话

java 微型数据库用肉眼看,基准测试似乎只是确定执行某些代码需要花费多长时间的简单问题。 但是,通常情况下,这是幼稚的方法。 提供具有准确和可重复结果的有意义的基准并非易事。 在本文中,我们将向您介绍OpenJDK代码工具项目&a…

mysql快速随机_MySQL随机取数据最高效的方法

mysql随机取数据最高效率的方法发现在SQL语句里有一个 ORDER BY rand() 这样的一个语句,这个说是用着方便,但是效率实在是太低了,于是我用了以下的方法来优化,就是用JOIN表的方法来达到这个取随机数据行的方法,你可以用…

部署被测软件应用和中间件_使用FlexDeploy对融合中间件应用程序进行自动化软件测试...

部署被测软件应用和中间件自动化软件测试是任何软件组织都必须执行的强制性活动之一,以保证其产品质量。 但是,此过程通常变得相当复杂,尤其是涉及由多个不同部分组成的现代复杂系统的自动化测试时。 所有这些部分都基于不同的技术&#xff0…