适配器设计模式示例
本文是我們名為“ Java設計模式 ”的學院課程的一部分。
在本課程中,您將深入研究大量的設計模式,并了解如何在Java中實現和利用它們。 您將了解模式如此重要的原因,并了解何時以及如何應用模式中的每一個。 在這里查看 !
目錄
1.適配器模式 2.搶救適配器 3.解決問題 4.類適配器 5.何時使用適配器模式 6.下載源代碼1.適配器模式
Max的軟件開發人員已在一個電子商務網站上工作。 該網站允許用戶在線購物和付款。 該站點與第三方支付網關集成在一起,用戶可以通過該網關使用信用卡支付賬單。 一切進展順利,直到他的經理打電話給他要求更改項目。
經理告訴他,他們正計劃更改支付網關供應商,他必須在代碼中實現這一點。
這里出現的問題是該站點連接到采用Xpay類型對象的Xpay支付網關。 新的供應商PayD僅允許對象的PayD類型允許該過程。 Max不想更改引用了XPay類型對象的100個類的整個集合。 這也增加了已經在生產中運行的項目的風險。 他都不能更改支付網關的第三方工具。 由于代碼的兩個不同部分之間的接口不兼容,導致出現了問題。 為了使過程正常進行,Max需要找到一種使代碼與供應商提供的API兼容的方法。
Xpay API的當前代碼
圖1
現在,當前代碼接口與新供應商的接口不兼容。
圖2
2.搶救適配器
Max在這里需要的是一個適配器,它可以位于代碼和供應商的API之間,并可以使流程順暢進行。 但是在解決方案之前,讓我們首先了解一下適配器是什么以及它如何工作。
有時,可能會出現兩個對象無法放在一起的情況,因為它們應該按順序完成工作。 當我們嘗試將舊代碼與新代碼集成在一起時,或在代碼中更改第三方API時,可能會出現這種情況。 這是由于兩個對象的接口不兼容而導致的。
適配器模式使您可以使對象或類公開的內容適應另一個對象或類期望的內容。 它將類的接口轉換為客戶端期望的另一個接口。 它允許類因接口不兼容而無法一起工作。 它允許修復對象和類之間的接口,而無需直接修改對象和類。
您可以將適配器視為真實世界的適配器,該適配器用于連接無法直接連接的兩個不同的設備。 適配器位于這些設備之間,它從設備中獲取流量并將其以所需的形式提供給其他設備,否則由于接口不兼容而無法獲得。
適配器使用合成來存儲應該適應的對象,并在調用適配器的方法時,將這些調用轉換為適應的對象可以理解的內容,并將這些調用傳遞給適應的對象。 調用適配器的代碼永遠不需要知道它不是在處理它認為的對象類型,而是在處理對象。
圖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.類適配器
適配器有兩種類型,對象適配器和類適配器。 到目前為止,我們已經看到了使用對象組成的對象適配器的示例,而類適配器則依靠多重繼承來使一個接口適應另一個接口。 由于Java不支持多重繼承,因此我們無法向您展示多重繼承的示例,但是您可以牢記這一點,并可以用您喜歡的支持多種繼承的面向對象語言(如c ++)之一來實現。
為了實現類適配器,適配器將從Target公開繼承,并從Adaptee私有繼承。 結果,適配器將是Target的子類型,但不是Adaptee的子類型。
圖5
5.何時使用適配器模式
在以下情況下應使用適配器模式:
6.下載源代碼
這是有關適配器模式的課程。 您可以在此處下載源代碼: AdapterPattern-Project
翻譯自: https://www.javacodegeeks.com/2015/09/adapter-design-pattern.html
總結
- 上一篇: 服务器网卡怎么设置(服务器怎么配置网卡)
- 下一篇: 备忘录设计模式示例