Что это такое
Паттерн Адаптер (Adapter) позволяет классу с неподходящим интерфейсом соответствовать интерфейсу, который ожидает ваш код, — как дорожный переходник между иностранной розеткой и вашим зарядным устройством.
Изменить старый класс нельзя (он взят из библиотеки, или от него зависит другой код). Поэтому вы оборачиваете его в небольшой класс, который реализует нужный вам протокол и преобразует вызовы.
Пример: старый принтер в роли логгера
Нашему коду нужен Logger с методом log(message). Устаревший класс предлагает только write_line(prefix, text). Адаптер хранит старый класс и преобразует один вызов в другой.
Адаптер преобразует вызов
run() работает с любым Logger; адаптер делает устаревший принтер одним из них, не трогая его код.
Вывод: полная программа на Python
from typing import Protocol
# Протокол, который ожидает наш код.
class Logger(Protocol):
def log(self, message: str) -> None: ...
# Старый библиотечный класс с другим методом — изменить его нельзя.
class LegacyPrinter:
def write_line(self, prefix: str, text: str) -> None:
print(prefix + " | " + text)
# Адаптер подгоняет старый класс под новый протокол.
class PrinterAdapter:
def __init__(self, legacy: LegacyPrinter):
self.legacy = legacy
def log(self, message: str) -> None:
self.legacy.write_line("LOG", message)
def run(logger: Logger) -> None:
logger.log("сервис запущен")
logger.log("запрос обработан")
run(PrinterAdapter(LegacyPrinter()))
Когда его использовать
Используйте его, когда работающий код и нужный интерфейс не совпадают, а изменить ни одну из сторон нельзя (или не следует) — сторонние библиотеки, устаревший код, сгенерированный код.
Не используйте его, когда обе стороны принадлежат вам — тогда просто измените одну из них, чтобы они совпали. Адаптер между двумя классами, которые вы контролируете, — это обходной путь вместо решения, которое вы могли бы просто принять.
Плюсы и минусы
Плюсы: старый и новый код работают вместе без изменений в каждом из них; преобразование находится в одном небольшом классе, который легко тестировать.
Минусы: ещё один шаг, через который приходится читать код; множество адаптеров, наложенных друг на друга, — признак того, что сами интерфейсы нужно переработать.