← Назад к вопросам

В чем разница между фасадом и адаптером?

2.3 Middle🔥 151 комментариев
#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Фасад (Facade) vs Адаптер (Adapter)

Оба паттерна решают проблемы интеграции и упрощения работы с кодом, но подходят к этому по-разному.

Адаптер (Adapter) — преобразование интерфейса

Адаптер преобразует один интерфейс в другой, чтобы несовместимые компоненты работали вместе.

class Duck:
    def quack(self):
        pass
    def fly(self):
        pass

class Turkey:
    def gobble(self):
        print("Gobble gobble")
    def fly(self):
        print("Turkey flying")

# АДАПТЕР: Преобразуем Turkey в Duck
class TurkeyAdapter(Duck):
    def __init__(self, turkey):
        self.turkey = turkey
    
    def quack(self):
        self.turkey.gobble()
    
    def fly(self):
        self.turkey.fly()

turkey = Turkey()
adapter = TurkeyAdapter(turkey)
adapter.quack()  # Работает!

def duck_simulator(duck):
    duck.quack()
    duck.fly()

duck_simulator(adapter)  # Turkey работает как Duck

Фасад (Facade) — упрощение сложной системы

Фасад скрывает сложность системы и предоставляет простой интерфейс для работы с несколькими компонентами.

class Amplifier:
    def on(self): print("Усилитель включён")
    def off(self): print("Усилитель выключен")
    def set_volume(self, level): print(f"Громкость: {level}")

class DVDPlayer:
    def on(self): print("DVD включен")
    def off(self): print("DVD выключен")
    def play(self, movie): print(f"Проигрываем {movie}")

class Projector:
    def on(self): print("Проектор включен")
    def off(self): print("Проектор выключен")

class Lights:
    def dim(self, level): print(f"Освещение: {level}%")

# ФАСАД: Скрывает сложность
class HomeTheaterFacade:
    def __init__(self, amp, dvd, projector, lights):
        self.amp = amp
        self.dvd = dvd
        self.projector = projector
        self.lights = lights
    
    def watch_movie(self, movie):
        print("Подготовка к просмотру фильма...")
        self.lights.dim(10)
        self.projector.on()
        self.amp.on()
        self.amp.set_volume(5)
        self.dvd.on()
        self.dvd.play(movie)
    
    def end_movie(self):
        print("Завершение просмотра...")
        self.lights.dim(100)
        self.projector.off()
        self.amp.off()
        self.dvd.off()

theater = HomeTheaterFacade(
    Amplifier(), DVDPlayer(), Projector(), Lights()
)
theater.watch_movie("Матрица")
theater.end_movie()

Сравнение в таблице

АспектАдаптерФасад
ЦельПреобразовать интерфейсУпростить сложную систему
ПроблемаНесовместимые интерфейсыСложность системы
НаправлениеДвустороннийОдностороннее
Количество компонентовОбычно 1-2Много
Отношение к исходному кодуОборачивает один объектСкрывает множество объектов

Практические примеры

Адаптер: интеграция разных API

class HttpClient:
    def get(self, url):
        pass
    def post(self, url, data):
        pass

import requests

class RequestsAdapter(HttpClient):
    def get(self, url):
        response = requests.get(url)
        return response.json()
    
    def post(self, url, data):
        response = requests.post(url, json=data)
        return response.json()

api_client = RequestsAdapter()
api_client.get("https://api.example.com/users")

Адаптер: старый и новый код

class LegacyPaymentProcessor:
    def process_payment(self, cc_number, amount):
        print(f"Обработка платежа: {cc_number} на сумму {amount}")

class ModernPaymentProcessor:
    def process_secure_payment(self, token, amount):
        print(f"Безопасная обработка: {token} на сумму {amount}")

class PaymentAdapter(ModernPaymentProcessor):
    def __init__(self, legacy_processor):
        self.legacy = legacy_processor
    
    def process_payment_v2(self, cc_number, amount):
        token = f"TOKEN_{hash(cc_number)}"
        self.process_secure_payment(token, amount)

processor = PaymentAdapter(LegacyPaymentProcessor())

Фасад: работа с БД

class QueryBuilder:
    def __init__(self):
        self.conditions = []
    
    def where(self, field, value):
        self.conditions.append(f"{field} = {value}")
        return self

class ConnectionPool:
    def get_connection(self):
        return "connection"

class Logger:
    def log_query(self, query):
        print(f"Executing: {query}")

class DatabaseFacade:
    def __init__(self):
        self.query_builder = QueryBuilder()
        self.pool = ConnectionPool()
        self.logger = Logger()
    
    def find_users(self, **filters):
        qb = QueryBuilder()
        for field, value in filters.items():
            qb.where(field, value)
        
        query = " ".join(qb.conditions)
        self.logger.log_query(query)
        
        conn = self.pool.get_connection()
        return f"Results from: {query}"

db = DatabaseFacade()
users = db.find_users(active=True, role="admin")

Когда использовать что

Адаптер используй когда:

  • Нужно интегрировать несовместимые интерфейсы
  • Работаешь с third-party библиотеками
  • Нужна поддержка нескольких версий API
  • Преобразуешь данные из одного формата в другой

Фасад используй когда:

  • Система имеет много компонентов
  • Хочешь упростить API для клиентов
  • Нужно скрыть внутренние детали реализации
  • Уменьшить связанность компонентов

Важное отличие

  • АДАПТЕР: я хочу, чтобы несовместимое работало вместе — СОВМЕСТИМОСТЬ
  • ФАСАД: я хочу упростить использование сложной системы — УПРОЩЕНИЕ
  • Адаптер: "Я буду говорить на языке обеих сторон"
  • Фасад: "Используй меня, я все скрыл"
В чем разница между фасадом и адаптером? | PrepBro