当我们要连接两个不兼容的接口或类以使它们可以一起工作时,使用适配器设计模式。当我们拥有需要集成的旧系统或第三方库时,这特别有用,但是它使用与其他代码的界面没有相同的接口。
在GO中,我们可以使用接口,结构和组成来实现适配器模式。我们可以创建一个界面,以定义我们需要使用的方法,然后创建一个实现接口并包裹不兼容接口或类的适配器结构。
这是电子商务系统中适配器模式的一个示例:
假设我们有一个电子商务系统,该系统使用付款网关处理付款。付款网关提供了我们需要集成的付款API。但是,我们的系统具有不同的付款处理界面,我们可以修改付款网关的API。
为了解决此问题,我们可以创建一个适配器,以实现我们的付款接口并包装付款网关的API。这是代码的外观:
type PaymentGateway struct {
// Payment gateway API implementation
}
func (pg *PaymentGateway) ProcessPayment(amount float64, cardNumber string, cardExpMonth string, cardExpYear string, cardCVV string) error {
// Process payment using payment gateway API
}
type PaymentAdapter struct {
paymentGateway *PaymentGateway
}
func NewPaymentAdapter() *PaymentAdapter {
return &PaymentAdapter{&PaymentGateway{}}
}
func (pa *PaymentAdapter) ProcessPayment(amount float64, card Card) error {
return pa.paymentGateway.ProcessPayment(amount, card.Number, card.ExpMonth, card.ExpYear, card.CVV)
}
在此示例中,PaymentGateway结构代表付款网关的API实现,PayayAdapter结构实现了我们的付款接口并包装了PaymentGateway结构。 NewPaymentAdapter函数创建了一个新的PaymayAdapter,并初始化了PaymentGateway实例变量。 PaymandAdapter中的ProcessPay方法调用PaymentGateway中的ProcessPayment方法,以所需的参数传递。
这是贸易生态系统中适配器模式的另一个示例:
假设我们有一个贸易生态系统,可以使用不同的协议与各种交易伙伴进行通信。一些合作伙伴使用REST API,而另一些合作伙伴使用肥皂API。为了简化我们的代码并使其更模块化,我们可以为实现一个共同接口的每个合作伙伴的API创建适配器。
type TradeAPI interface {
GetQuote(symbol string) (float64, error)
PlaceOrder(order Order) (string, error)
}
type RestTradeAPI struct {
// REST API implementation
}
func (rta *RestTradeAPI) GetQuote(symbol string) (float64, error) {
// Call REST API to get quote
}
func (rta *RestTradeAPI) PlaceOrder(order Order) (string, error) {
// Call REST API to place order
}
type SoapTradeAPI struct {
// SOAP API implementation
}
func (sta *SoapTradeAPI) GetQuote(symbol string) (float64, error) {
// Call SOAP API to get quote
}
func (sta *SoapTradeAPI) PlaceOrder(order Order) (string, error) {
// Call SOAP API to place order
}
type TradeAPIAdapter struct {
tradeAPI TradeAPI
}
func NewTradeAPIAdapter(tradeAPI TradeAPI) *TradeAPIAdapter {
return &TradeAPIAdapter{tradeAPI}
}
func (taa *TradeAPIAdapter) GetQuote(symbol string) (float64, error) {
return taa.tradeAPI.GetQuote(symbol)
}
func (taa *TradeAPIAdapter) PlaceOrder(order Order) (string, error) {
return taa.tradeAPI.PlaceOrder(order)
}
在此示例中,我们定义了一个TradeAPI
接口,该接口指定了我们需要与交易合作伙伴进行通信的方法。然后,我们为其余和肥皂API创建此接口的实现。最后,我们创建了一个TradeAPIAdapter
struct,该结构包装了TradeAPI
接口的实现并实现了TradeAPI
接口本身。
使用TradeAPIAdapter
,我们可以抽象不同的API之间的差异,并使用通用界面与我们所有交易伙伴进行通信。
*在代理设计模式中,我们通常遵循类似的事物(界面,结构,组成)。
*
因此,代理设计模式与适配器设计模式之间有什么相似之处吗?
是的,适配器设计模式与代理设计模式之间存在相似之处。两种模式都涉及创建一个新对象,该对象充当客户端代码和另一个对象之间的中介,但它们是出于不同的原因。
当我们需要连接两个不兼容的接口或类以使它们可以一起工作时,请使用适配器模式。我们创建一个适配对象,该对象包裹不兼容的对象并实现客户端代码期望的接口。
另一方面,当我们要控制对象访问或提供其他功能而不修改对象本身时,使用代理模式。我们创建了一个外观和行为的代理对象,该对象类似于原始对象,但添加了一些其他行为或约束,例如缓存结果或限制对某些方法的访问。
两种模式都使用构图来创建一个新对象,将其委派给原始对象,但出于不同的原因而这样做。适配器模式的重点是创建与现有代码兼容的新界面,而代理模式则重点是将功能添加到现有接口。
结论:使用哪种模式的选择取决于系统的特定需求。如果我们需要连接两个不兼容的接口或类,则适配器模式是最佳选择。如果我们需要添加功能或控制对象的访问,则代理模式是更好的选择。
通过了解这两种模式之间的相似性和差异,我们可以选择最适合我们需求的一种模式,并构建更强大和灵活的系统。