适配器模式:协议转换与遗留集成
适配器模式:协议转换与遗留集成
适配器模式概述
适配器模式将一个类的接口转换成客户端期望的另一个接口,使原本接口不兼容的类可以一起工作。在架构设计中,适配器模式是系统集成的核心手段,解决不同系统间的协议差异、数据格式差异和接口差异。
// 目标接口
public interface PaymentProcessor {
PaymentResult process(PaymentRequest request);
}
// 适配器 - 将第三方支付网关适配到统一接口
public class AlipayAdapter implements PaymentProcessor {
private final AlipayClient alipayClient;
public PaymentResult process(PaymentRequest request) {
// 转换请求格式
AlipayTradePayRequest aliRequest = new AlipayTradePayRequest();
aliRequest.setOutTradeNo(request.getOrderId());
aliRequest.setTotalAmount(request.getAmount().toString());
aliRequest.setSubject(request.getDescription());
// 调用支付宝API
AlipayTradePayResponse aliResponse = alipayClient.execute(aliRequest);
// 转换响应格式
return PaymentResult.builder()
.success("10000".equals(aliResponse.getCode()))
.transactionId(aliResponse.getTradeNo())
.message(aliResponse.getSubMsg())
.build();
}
}
协议转换适配器
不同系统可能使用不同的通信协议,适配器模式统一协议差异。例如将HTTP REST适配为gRPC,或适配消息队列协议。
# HTTP到gRPC协议适配器
class HTTPToGRPCAdapter:
def __init__(self, grpc_stub):
self.stub = grpc_stub
async def handle_http_request(self, http_request: dict) -> dict:
# HTTP JSON -> Protobuf转换
grpc_request = CreateOrderRequest(
user_id=http_request['userId'],
items=[
OrderItem(
product_id=item['productId'],
quantity=item['quantity']
)
for item in http_request['items']
],
total_amount=Decimal(str(http_request['totalAmount']))
)
# 调用gRPC服务
grpc_response = await self.stub.CreateOrder(grpc_request)
# Protobuf -> HTTP JSON转换
return {
'orderId': grpc_response.order_id,
'status': grpc_response.status.name,
'createdAt': grpc_response.created_at.isoformat()
}
遗留系统封装
将遗留系统的接口封装为现代化接口,新系统通过适配器访问遗留系统,避免大规模重构。
// 遗留系统适配器 - 封装老旧COM组件
public class LegacyInventoryAdapter : IInventoryService
{
private readonly COMInventoryLibrary.LegacyInventory _legacySystem;
public LegacyInventoryAdapter()
{
_legacySystem = new COMInventoryLibrary.LegacyInventory();
}
public async Task<StockInfo> GetStock(string productId)
{
// 转换新接口到遗留接口格式
var legacyResult = _legacySystem.CheckStock(productId, "WAREHOUSE01");
// 转换遗留接口返回值
return new StockInfo
{
ProductId = productId,
Quantity = legacyResult.QtyAvailable,
Warehouse = legacyResult.WarehouseCode,
LastUpdated = DateTime.FromFileTime(legacyResult.UpdateTime)
};
}
public async Task<bool> DeductStock(string productId, int quantity)
{
var result = _legacySystem.ReserveStock(productId, quantity, "SYSTEM");
return result.ReturnCode == 0;
}
}
多数据源统一适配
使用适配器模式统一不同数据源的访问接口,实现透明的数据源切换和多数据源聚合。
// 统一存储适配器接口
type StorageAdapter interface {
Get(ctx context.Context, key string) ([]byte, error)
Set(ctx context.Context, key string, value []byte, ttl time.Duration) error
Delete(ctx context.Context, key string) error
}
// Redis适配器
type RedisAdapter struct {
client *redis.Client
}
func (r *RedisAdapter) Get(ctx context.Context, key string) ([]byte, error) {
return r.client.Get(ctx, key).Bytes()
}
// 本地缓存适配器
type LocalCacheAdapter struct {
cache *cache.Cache
}
func (l *LocalCacheAdapter) Get(ctx context.Context, key string) ([]byte, error) {
val, found := l.cache.Get(key)
if !found {
return nil, ErrKeyNotFound
}
return val.([]byte), nil
}