Ответ
Паттерн Адаптер (Adapter) — это структурный паттерн проектирования, который позволяет объектам с несовместимыми интерфейсами работать вместе. Он выступает в роли обертки, преобразуя интерфейс одного класса (адаптируемого объекта, или adaptee) в интерфейс, ожидаемый клиентом (целевой интерфейс, или target).
Назначение: Основная цель Адаптера — обеспечить взаимодействие между классами, которые не могут работать вместе напрямую из-за несовместимости их интерфейсов, без изменения исходного кода этих классов.
Типы Адаптеров:
- Адаптер объекта (Object Adapter): Использует композицию. Адаптер содержит экземпляр адаптируемого объекта и делегирует ему вызовы, преобразуя их. Это наиболее распространенный подход в Python.
- Адаптер класса (Class Adapter): Использует множественное наследование (если язык поддерживает). Адаптер наследует как от целевого интерфейса, так и от адаптируемого класса. В Python менее применим из-за особенностей наследования и предпочтения композиции.
Пример (Object Adapter на Python):
Представим, что у нас есть старая система логирования, которая принимает сообщения только через метод log_message_old_format, а новая система ожидает метод log_message.
# Адаптируемый класс (Adaptee) - старая система
class OldLogger:
def log_message_old_format(self, message: str):
print(f"[OLD LOG]: {message}")
# Целевой интерфейс (Target) - что ожидает клиент
class NewLoggerInterface:
def log_message(self, message: str):
raise NotImplementedError("Должен быть реализован подклассом")
# Адаптер (Adapter)
class LoggerAdapter(NewLoggerInterface):
def __init__(self, old_logger: OldLogger):
self._old_logger = old_logger
def log_message(self, message: str):
# Преобразуем вызов нового интерфейса в вызов старого
self._old_logger.log_message_old_format(f"[ADAPTED] {message}")
# Клиентский код, который работает с новым интерфейсом
def client_code(logger: NewLoggerInterface, text: str):
logger.log_message(text)
# Использование:
old_logger_instance = OldLogger()
# Клиент не может напрямую использовать OldLogger:
# client_code(old_logger_instance, "Это сообщение не сработает") # Ошибка атрибута
# Используем адаптер для совместимости
adapter = LoggerAdapter(old_logger_instance)
client_code(adapter, "Сообщение через адаптер")
# Вывод:
# [OLD LOG]: [ADAPTED] Сообщение через адаптер
Когда использовать паттерн Адаптер?
- Интеграция: Когда нужно использовать существующий класс, но его интерфейс не соответствует потребностям.
- Сторонние библиотеки: При работе с библиотеками, которые имеют полезную функциональность, но неудобный или несовместимый API.
- Унификация: Для предоставления единого интерфейса к нескольким классам с похожей, но не идентичной функциональностью.
Преимущества:
- Повторное использование кода: Позволяет использовать существующие классы без их модификации.
- Разделение ответственности: Отделяет логику преобразования интерфейсов от основной бизнес-логики.
- Гибкость: Позволяет легко заменять адаптируемые классы, не затрагивая клиентский код.
Недостатки:
- Увеличение сложности: Добавляет новые классы, что может усложнить структуру проекта.
- Производительность: Небольшие накладные расходы из-за дополнительного уровня абстракции (обычно незначительные).