The previous three articles covered the proxy pattern, the bridge pattern, and the decorator pattern, and this time the adapter pattern.

The adapter pattern is simpler and easier to understand. The adapter pattern can be thought of as a “compensation pattern” to remedy design flaws. Applying this model is a “no choice” move.

UML class diagrams location: www.processon.com/diagraming/…

This article is linked to: github.com/shidawuhen/…

Definition 1.

1.1 Adapter Mode

Adapter pattern: Transforms the interface of one class into another interface that the customer wants. The Adapter pattern enables classes to work together that would otherwise not work together due to interface incompatibilities.

UML:

1.2 analysis

The UML diagram shows that Adapter and Adaptee are associated, but Adapter and Adaptee can also be inherited. In this case, most of the Adaptee member functions are consistent with Target, and only a few need to be modified. Inheritance can reduce code changes. If most of the Adaptee member functions and Target do not agree, it is best to use composition, after all, composition is better than inheritance. Of course, it doesn’t matter with Go, since only composition has no inheritance, and anonymous composition can directly reuse the functionality of composite objects.

The Adapter pattern is also relatively simple to use. The core is to repackage the Adaptee with Adapter to make it meet the requirements of Target.

2. Application scenarios

Consider using the adapter pattern in the following scenarios:

  1. Encapsulating flawed interface design: For example, if the interface design of an imported external system has flaws that affect the testability of our own code, we can consider using the adapter pattern to bring the imported system closer to our own system design

  2. Unify the interface design of multiple classes: If a function depends on multiple external systems, and the capabilities of these external systems are similar but the interface is not unified, you can use the adapter mode, relying on the inheritance, polymorphic characteristics, so that the caller can use the external system in an aggregate way, improve the code extensibility

  3. Substitution of dependent external systems: If a function has multiple external systems to choose from, we can define a Target interface that ADAPTS the external system to the Target so that the substitution of external systems can take advantage of polymorphism

  4. Compatible with the interface of the old version: Function A in the old version is abandoned in the new version, and A will be replaced by B. In order not to affect users, there will still be A in the new version, but its internal implementation is entrusted to B

  5. Adapt data to different formats: Sometimes data sources and formats vary, so you need to adapt the data to a unified format and then process the data. You can also use the adapter mode

I use the adapter pattern in my project, mainly dealing with data adaptation. In the previous payment gateway, the data returned by each third party was inconsistent. In order to conform to the format defined by the payment system, adaptation must be carried out. There are a lot of such places, so I will talk about the reconciliation function. For other content about payment, you can refer to this article on how to effectively connect with third-party payment.

3. Code implementation

The so-called reconciliation refers to taking the payment order information within a specified time from the third-party payment company and comparing it with the internal payment order information of the system, which is mainly used to find payment abnormalities

1. The payment gateway has data, but the third party does not

– Maybe it was hacked, the user didn’t actually pay, but we shipped it

– There is a problem with the code, the user did not complete the payment, but the system thinks the payment was successful

– Incomplete data provided by the third party

2. The payment gateway does not have data, but the third party does

– The user paid successfully, but either synchronous or asynchronous notification failed

3. The amount is inconsistent

– There is a problem with the code, the amount of payment initiated by the e-commerce is inconsistent with the amount actually called by the third party

– There are problems with third-party data

The logic for comparison is consistent, but the data format of third-party payment bill is not consistent, so it is necessary to convert the data into a standard format first.

package main

import (
	"fmt"
	"time"
)

/** * @author: Jason Pang * @description: Statement data */
type StatementItem struct {
	OrderId       string // System id
	TransactionId string // Third party transaction id
	Amount        int64  // Amount of payment, unit: minute
	PaymentTime   int64  // Order payment time
}

/** * @author: Jason Pang * @description: Obtain reconciliation data from a third party */
type StatementData interface {
	GetStatementData(startTime int64, endTime int64) []*StatementItem
}

/** * @author: Jason Pang * @description: WX pay */
type WXStatementData struct{}func (w *WXStatementData) GetStatementData(startTime int64, endTime int64)[] *StatementItem {
	fmt.Println("Reconciliation data obtained from WX, payment time needs to be formatted as time stamp")
	return []*StatementItem{
		{
			OrderId:       "WX order 222",
			TransactionId: "WX payment Slip Number",
			Amount:        999,
			PaymentTime:   time.Date(2014.1.7.5.50.4.0, time.Local).Unix(),
		},
	}
}

/** * @author: Jason Pang * @description: ZFB pay */
type ZFBStatementData struct{}func (z *ZFBStatementData) GetStatementData(startTime int64, endTime int64)[] *StatementItem {
	fmt.Println("The amount of the reconciliation data obtained from ZFB needs to be converted from yuan to cents.")
	return []*StatementItem{
		{
			OrderId:       "ZFB order 111",
			TransactionId: "ZFB Payment Slip No.",
			Amount:        99.9 * 100,
			PaymentTime:   1389058332,}}}/** * @author: Jason Pang * @description: Reconciliation function * @param list Statements obtained from a third party * @return bool */
func DoStatement(list []*StatementItem) bool {
	fmt.Println("Start reconciliation.")
	fmt.Println("Obtain payment orders from its own system for a specified period of time.")
	for _, item := range list {
		fmt.Println(item.OrderId + "Reconciliation with system payment slips")
	}
	fmt.Println("Reconciliation completed")
	return true
}

func main(a) {
	wx := &WXStatementData{}
	zfb := &ZFBStatementData{}
	stattementData := []StatementData{
		wx,
		zfb,
	}
	for _, s := range stattementData {
		DoStatement(s.GetStatementData(1389058332.1389098332))}}Copy the code

Output:

➜ myproject go run main.go

The reconciliation data obtained from WX, the payment time needs to be formatted as a timestamp

To check for

Retrieves payment orders from its own system for a specified period of time

WX Order 222 is reconciled with the system payment order

Check for completion

For the reconciliation data obtained from ZFB, the amount should be converted from yuan to cents

To check for

Retrieves payment orders from its own system for a specified period of time

Check ZFB order 111 with the system payment order

Check for completion

PS: The structure of the statement is defined in the code. In the future, it can participate in the reconciliation as long as the StatementData interface is realized, and the expansibility is excellent.

conclusion

The adapter pattern is simple and easy to use, and can greatly improve extensibility and elegance when used in the right scenario.

The adapter pattern has some similarities with the proxy, decorator, and bridge pattern, which we summarize here as well:

Proxy mode: The proxy mode defines a proxy class for the original class without changing the interface of the original class. The primary purpose of the proxy mode is to control access, rather than enhance functionality, which is the biggest difference from the decorator mode.

Decorator pattern: The Decorator pattern enhances the functionality of the original class without changing the interface of the original class and supports nested use of multiple decorators.

Adapter pattern: The adapter pattern is an afterthought strategy. The adapter provides a different interface from the original class, whereas the proxy and decorator patterns provide the same interface as the original class.

Bridge pattern: The purpose of the bridge pattern is to separate the interface part from the implementation part so that they can be changed relatively easily and independently.

The last

If you like my article, you can follow my public account (Programmer Malatang)

My personal blog is shidawuhen.github. IO /

Review of previous articles:

recruitment

  1. Bytes to beat | push big 24:00

  2. Bytes to beat | headlines today guangzhou server push r&d engineers

  3. Bytes to beat | trill electricity now hiring front-end development project in Shanghai

  4. Bytes to beat | trill electricity senior server-side development engineer – trading in Shanghai

  5. Bytes to beat | trill electric ShangWuHan server-side development engineer (senior)

  6. Bytes to beat | fly book big customer push product manager

  7. Bytes to beat | trill electricity service side technical posts vacant

  8. Bytedance recruitment special

Design patterns

  1. Go Design Mode (13)- Decorator mode

  2. Go Design Mode (12)- Bridge mode

  3. Go Design Pattern (11)- Proxy pattern

  4. Go Design Mode (10)- Prototype mode

  5. Go Design Mode (9)- Builder mode

  6. Go Design Pattern (8)- Abstract Factory

  7. Go Design Mode (7)- Factory Mode

  8. Go Design Pattern (6)- Singleton pattern

  9. Go Design Pattern (5)- Class diagram symbolic representation

  10. Go Design Pattern (4)- Code writing optimization

  11. Go Design Pattern (4)- Code writing

  12. Go Design Patterns (3)- Design principles

  13. Go Design Pattern (2)- Object-oriented analysis and design

  14. Go Design Pattern (1)- Syntax

language

  1. No more fear of not getting Gin request data

  2. Understand pprof

  3. Go tool generate

  4. Go singleton implementation scheme

  5. Implementation principle of Go channel

  6. Implementation principle of Go timer

  7. Beego framework use

  8. Golang source BUG tracking

  9. Gin framework concise version

  10. Gin source code analysis

architecture

  1. The paging check pit is designed

  2. Payment access general issues

  3. Current limiting 2

  4. Seconds kill system

  5. Distributed systems and consistency protocols

  6. Service framework and registry for microservices

  7. Discussion on Micro-service

  8. Current limiting implementation 1

  9. CDN request process details

  10. Common Cache tips

  11. How to effectively connect with third-party payment

  12. Algorithm is summarized

storage

  1. MySQL development specification

  2. Redis implements distributed locking

  3. The implementation principle of atomicity, consistency and persistence of transactions

  4. InnoDB locks and transactions

network

  1. HTTP2.0 basics tutorial

  2. HTTPS Configuration Combat

  3. HTTPS Connection Process

  4. TCP Performance Optimization

tool

  1. GoLand Practical skills

  2. Automatically generate go struct from mysql table

  3. Markdown editor recommends – Typora

Reading notes

  1. Selected by MAO

  2. The principle of

  3. History As A Mirror

  4. Agile revolution

  5. How to exercise your memory

  6. Simple Logic – After reading

  7. Hot Wind – After reading

  8. Analects of Confucius – After reading

  9. Sun Tzu’s Art of War – Reflections from reading

thinking

  1. Struggle to mobilize all forces for victory

  2. Anti-liberalism

  3. practical

  4. The standard by which you judge yourself

  5. Service team holiday shift plan

  6. Project process management

  7. Some thoughts on project management

  8. Some thoughts on product manager

  9. Thinking about programmer career development

  10. Thinking about code review