适配器设计模式示例

本文是我们名为“ 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,一经查实,立即删除!

相关文章

[转]Linux下g++编译与使用静态库(.a)和动态库(.os) (+修正与解释)

在windows环境下,我们通常在IDE如VS的工程中开发C项目,对于生成和使用静态库(*.lib)与动态库(*.dll)可能都已经比较熟悉,但是,在linux环境下,则是另一套模式,…

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

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

JAVA Junit error java.lang.SecurityException: class junit.framework.JUnit4TestCaseFacade

运行junit4时报错: java.lang.SecurityException: class "junit.framework.JUnit4TestCaseFacade"s signer information does not match signer information of other classes in the same package at java.lang.ClassLoader.checkCerts(Unknown Source) at java.lan…

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

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

复制选中的listbox内容

private void lt_log_MouseClick(object sender, MouseEventArgs e){Clipboard.SetDataObject(lt_log.SelectedItem.ToString()); }转载于:https://www.cnblogs.com/XuPengLB/p/5779554.html

heroku_WhateverOrigin –与Heroku和Play对抗原产地政策! 构架

heroku不久前,在编写 Bitcoin Pie时 ,我发现有必要克服臭名昭著的Same Origin Policy ,该政策限制了运行在客户端浏览器上的javascript可以访问的域。 通过Stack Overflow,我找到了一个名为Any Origin的站点,这基本上是…

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中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 ! 目录 …

redis命令学习

清空所有flushall 转载于:https://www.cnblogs.com/dragkiss/p/5784814.html

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

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

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

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

web性能测试基础 知识(引用)

1.1基本概念 并发用户:用户并发一般发生在使用比较频繁的模块中,而且遇到异常通常都是程序的问题。 用户并发数量:在线用户数量是计算并发用户数量的主要依据之一。使用系统的用户数量*(5%~20%) 并发主要针对WEB服务器而言,是否并…

javafx动画_JavaFX:创建Sprite动画

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

java自定义迭代器作用_Java实现的自定义迭代器功能示例

本文实例讲述了Java实现的自定义迭代器功能。分享给大家供大家参考,具体如下:编写自己的Iterator,实现Iterator接口,这里多说一句,实现Iterable后,可以用“foreach”循环遍历你的对象。import java.util.It…

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中实现和利用它们。 您将了解模式如此重要的原因,并了解何时以及如何应用模式中的每一个。 在这里查看 ! 目录 …

java项目遇到的问题_java系列:项目中遇到的一些问题(持续更新中)

JSONArray去重的问题 JSONArray array = ["2","0","0","0","0","0"]; private String[] instanceAaary(JSONArray array) throws JSONException{String[] strs = new String[array.length()]; for (int i = 0; i …

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

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

Java tree set_Java TreeSet tailSet()方法

Java TreeSet tailSet()方法java.util.TreeSet.tailSet(E fromElement) 方法用于返回一组大于或等于指定元素的元素。1 语法public SortedSet tailSet(E fromElement)2 参数fromElement:这是返回集的最小边界值(包括该边界值)3 返回值返回此集合中元素大于或等于fro…

java map练习_JAVA Map练习

JAVA Map练习作者:萤火之森2015-04-21 12:46浏览:1203package pack3;import java.util.HashMap;import java.util.Iterator;import java.util.*;import java.util.Set;/*** 每一个学生都有对应的归属地* 学生Student 地址String* 学生属性:姓…