副标题: 90%的人不知道,适配器模式能让不兼容的接口协同工作
痛点:为什么你的第三方库总是难以集成?
2025年某项目需要集成3个不同的支付API,每个API的接口都不一样。问题出在哪?工程师没有使用适配器模式统一接口。
真相:适配器模式让接口不兼容的类可以一起工作。
| 模式 | 核心目的 | 典型场景 |
| 适配器 | 接口转换 | 第三方库集成、遗留代码 |
| 外观 | 简化接口 | 复杂子系统访问 |
一、适配器模式
1.1 什么是适配器模式
将一个类的接口转换成客户希望的另一个接口。
# 目标接口(客户期望的)
class PaymentProcessor:
def process_payment(self, amount):
pass
需要适配的类(不兼容的)
class LegacyPaymentGateway:
def make_payment(self, money):
print(f"旧网关支付: ${money}")
return True
def refund_payment(self, money):
print(f"旧网关退款: ${money}")
return True
类适配器(多重继承)
class LegacyPaymentAdapter(PaymentProcessor, LegacyPaymentGateway):
def process_payment(self, amount):
return self.make_payment(amount)
def refund(self, amount):
return self.refund_payment(amount)
对象适配器(组合)
class PaymentGatewayAdapter(PaymentProcessor):
def __init__(self, legacy_gateway):
self._gateway = legacy_gateway
def process_payment(self, amount):
return self._gateway.make_payment(amount)
def refund(self, amount):
return self._gateway.refund_payment(amount)
使用
legacy = LegacyPaymentGateway()
adapter = PaymentGatewayAdapter(legacy)
adapter.process_payment(100)
1.2 适配器模式vs桥接模式
# 适配器:改变接口
class Target:
def request(self):
pass
class Adaptee:
def specific_request(self):
pass
class Adapter(Target):
def __init__(self, adaptee):
self._adaptee = adaptee
def request(self):
self._adaptee.specific_request()
桥接:分离抽象和实现
class Implementor:
def operation(self):
pass
class RefinedImplementorA(Implementor):
def operation(self):
return "实现A"
class RefinedImplementorB(Implementor):
def operation(self):
return "实现B"
class Abstraction:
def __init__(self, implementor):
self._implementor = implementor
def operation(self):
return self._implementor.operation()
class RefinedAbstraction(Abstraction):
def extended_operation(self):
return self.operation() + " 扩展"
1.3 真实场景:数据库适配器
# 统一的数据库接口
class Database:
def connect(self):
pass
def query(self, sql):
pass
def close(self):
pass
MySQL适配器
class MySQLAdapter(Database):
def __init__(self, host, user, password):
self.host = host
self.user = user
self.password = password
self._conn = None
def connect(self):
import pymysql
self._conn = pymysql.connect(
host=self.host,
user=self.user,
password=self.password
)
print(f"连接 MySQL: {self.host}")
def query(self, sql):
if not self._conn:
raise RuntimeError("未连接")
with self._conn.cursor() as cursor:
cursor.execute(sql)
return cursor.fetchall()
def close(self):
if self._conn:
self._conn.close()
PostgreSQL适配器
class PostgreSQLAdapter(Database):
def __init__(self, host, user, password, database):
self.host = host
self.user = user
self.password = password
self.database = database
self._conn = None
def connect(self):
import psycopg2
self._conn = psycopg2.connect(
host=self.host,
user=self.user,
password=self.password,
database=self.database
)
print(f"连接 PostgreSQL: {self.host}")
def query(self, sql):
if not self._conn:
raise RuntimeError("未连接")
with self._conn.cursor() as cursor:
cursor.execute(sql)
return cursor.fetchall()
def close(self):
if self._conn:
self._conn.close()
使用
db = MySQLAdapter("localhost", "user", "pass")
db.connect()
results = db.query("SELECT * FROM users")
db.close()
二、外观模式
2.1 什么是外观模式
为子系统中的一组接口提供一个一致的界面。
# 子系统类
class CPU:
def freeze(self):
print("CPU: 冻结")
def jump(self, position):
print(f"CPU: 跳转到 {position}")
def execute(self):
print("CPU: 执行")
class Memory:
def load(self, position, data):
print(f"内存: 加载 {position} -> {data}")
class HardDrive:
def read(self, lba, size):
return f"硬盘数据: {lba}, {size}"
外观
class ComputerFacade:
def __init__(self):
self._cpu = CPU()
self._memory = Memory()
self._hard_drive = HardDrive()
def boot(self):
print("=== 启动电脑 ===")
self._cpu.freeze()
self._memory.load("0x00", self._hard_drive.read("100", "1024"))
self._cpu.jump("0x00")
self._cpu.execute()
print("=== 启动完成 ===")
使用
computer = ComputerFacade()
computer.boot()
2.2 简化复杂API
# 复杂的第三方API
class ComplexAPI:
def authenticate(self, username, password):
print(f"认证: {username}")
return "token123"
def get_user_profile(self, token):
print(f"获取用户: {token}")
return {"name": "Alice", "email": "alice@example.com"}
def update_user(self, token, data):
print(f"更新用户: {token}, {data}")
return True
def get_user_orders(self, token):
print(f"获取订单: {token}")
return [{"id": 1, "total": 99.99}]
def create_order(self, token, items):
print(f"创建订单: {token}, {items}")
return {"order_id": 123}
外观:简化API使用
class UserAPIFacade:
def __init__(self):
self._api = ComplexAPI()
self._token = None
def login(self, username, password):
self._token = self._api.authenticate(username, password)
return self._token
def get_profile(self):
if not self._token:
raise RuntimeError("未登录")
return self._api.get_user_profile(self._token)
def update_profile(self, data):
if not self._token:
raise RuntimeError("未登录")
return self._api.update_user(self._token, data)
def get_orders(self):
if not self._token:
raise RuntimeError("未登录")
return self._api.get_user_orders(self._token)
def create_order(self, items):
if not self._token:
raise RuntimeError("未登录")
return self._api.create_order(self._token, items)
使用
facade = UserAPIFacade()
facade.login("alice", "password")
profile = facade.get_profile()
orders = facade.get_orders()
三、实战案例
3.1 日志适配器
import logging
from datetime import datetime
统一的日志接口
class Logger:
def info(self, message):
pass
def error(self, message):
pass
def warning(self, message):
pass
FileLogger适配器
class FileLoggerAdapter(Logger):
def __init__(self, filename):
self._logger = logging.getLogger(filename)
self._logger.setLevel(logging.INFO)
if not self._logger.handlers:
handler = logging.FileHandler(filename)
formatter = logging.Formatter(
'%(asctime)s - %(levelname)s - %(message)s'
)
handler.setFormatter(formatter)
self._logger.addHandler(handler)
def info(self, message):
self._logger.info(message)
def error(self, message):
self._logger.error(message)
def warning(self, message):
self._logger.warning(message)
ConsoleLogger适配器
class ConsoleLoggerAdapter(Logger):
def __init__(self, name="app"):
self._logger = logging.getLogger(name)
self._logger.setLevel(logging.INFO)
if not self._logger.handlers:
handler = logging.StreamHandler()
formatter = logging.Formatter(
'[%(levelname)s] %(message)s'
)
handler.setFormatter(formatter)
self._logger.addHandler(handler)
def info(self, message):
self._logger.info(message)
def error(self, message):
self._logger.error(message)
def warning(self, message):
self._logger.warning(message)
使用
logger = FileLoggerAdapter('app.log')
logger.info("应用启动")
logger.error("发生错误")
3.2 通知系统外观
# 子系统
class EmailService:
def send(self, to, subject, body):
print(f"发送邮箱: {to}, {subject}")
class SMSService:
def send(self, phone, message):
print(f"发送短信: {phone}, {message}")
class PushService:
def send(self, user_id, title, message):
print(f"推送通知: {user_id}, {title}")
外观
class NotificationFacade:
def __init__(self):
self._email = EmailService()
self._sms = SMSService()
self._push = PushService()
def notify_user(self, user, message, channels=['email']):
"""统一通知接口"""
if 'email' in channels:
self._email.send(user['email'], '通知', message)
if 'sms' in channels:
self._sms.send(user['phone'], message)
if 'push' in channels:
self._push.send(user['id'], '新消息', message)
使用
user = {'id': 1, 'email': 'alice@example.com', 'phone': '13800138000'}
facade = NotificationFacade()
facade.notify_user(user, '您的订单已发货', channels=['email', 'push'])
3.3 第三方API集成
# 需要集成的第三方服务
class StripeAPI:
def create_customer(self, email):
return {'customer_id': 'cus_123'}
def create_charge(self, customer_id, amount):
return {'charge_id': 'ch_123'}
class PayPalAPI:
def create_account(self, email):
return {'account_id': 'pay_123'}
def execute_payment(self, account_id, amount):
return {'payment_id': 'pay_123'}
统一的支付接口
class PaymentGateway:
def create_customer(self, email):
pass
def charge(self, customer_id, amount):
pass
Stripe适配器
class StripeAdapter(PaymentGateway):
def __init__(self):
self._stripe = StripeAPI()
def create_customer(self, email):
result = self._stripe.create_customer(email)
return result['customer_id']
def charge(self, customer_id, amount):
result = self._stripe.create_charge(customer_id, amount)
return result['charge_id']
PayPal适配器
class PayPalAdapter(PaymentGateway):
def __init__(self):
self._paypal = PayPalAPI()
def create_customer(self, email):
result = self._paypal.create_account(email)
return result['account_id']
def charge(self, customer_id, amount):
result = self._paypal.execute_payment(customer_id, amount)
return result['payment_id']
使用
gateway = StripeAdapter()
customer_id = gateway.create_customer('alice@example.com')
charge_id = gateway.charge(customer_id, 100)
四、模式对比
4.1 适配器 vs 外观
# 适配器:转换接口
class Adaptee:
def specific_request(self):
pass
class Adapter:
def __init__(self, adaptee):
self._adaptee = adaptee
def request(self):
self._adaptee.specific_request()
外观:简化接口
class SubsystemA:
def method_a(self):
pass
class SubsystemB:
def method_b(self):
pass
class Facade:
def __init__(self):
self._a = SubsystemA()
self._b = SubsystemB()
def operation(self):
self._a.method_a()
self._b.method_b()
4.2 何时使用
| 场景 | 推荐模式 |
| 接口不兼容 | 适配器 |
| 接口太复杂 | 外观 |
| 需要复用旧代码 | 适配器 |
| 简化子系统访问 | 外观 |
五、最佳实践
| 场景 | 推荐方式 |
| 第三方库集成 | 适配器 |
| 遗留代码封装 | 适配器 |
| 复杂子系统 | 外观 |
| 统一接口 | 适配器 |
核心原则:
-
●适配器改变接口-
●外观简化接口-
●两者都能解耦,但目的不同-
结语
关键洞察:
-
●适配器模式:接口转换-
●外观模式:接口简化-
●类适配器用继承,对象适配器用组合-
●优先使用对象适配器(更灵活)-
互动
-
1.你用适配器集成过什么第三方库?-
2.外观模式和单例模式有什么区别?-
3.适配器模式会引入性能开销吗?-
版本: V1.0 | 2026-05-26 | Python设计模式系列
📚 推荐阅读
📝 摘要:今天深入学习静态代码分析技术,这是安全审计的核心技能。从 Python AST 模块到检测模式设计,收获满满!
发布于 202603
01-Python 环境搭建与第一个脚本
发布于 202603
【优化】Python代码优化与调试技巧
发布于 202603
KEYWORDS
LAD, IL, Python, 类, 对象
💡 如果你觉得这篇文章有帮助,请点个在看,分享给更多需要的人!
📝 关注我,获取更多实用干货~
🤝 有问题欢迎评论区留言交流!