В чем разница между паттернами Repository и Facade?

Ответ

Repository и Facade — это структурные паттерны, но они решают принципиально разные задачи.

Паттерн Repository

Назначение: Инкапсулирует логику доступа к данным, выступая в роли абстракции над хранилищем (БД, внешний API, файловая система). Он отделяет бизнес-логику от деталей работы с источниками данных.

Пример на C#:

// Абстракция репозитория
public interface IUserRepository
{
    User GetById(int id);
    void Add(User user);
    IEnumerable<User> Find(Expression<Func<User, bool>> predicate);
}

// Конкретная реализация
public class SqlUserRepository : IUserRepository
{
    private readonly AppDbContext _context;
    public SqlUserRepository(AppDbContext context) => _context = context;

    public User GetById(int id)
    {
        // Детали доступа к БД скрыты здесь
        return _context.Users.FirstOrDefault(u => u.Id == id);
    }
    // ... другие методы
}

Почему используется: Позволяет легко подменять источник данных (например, для тестов использовать InMemory-репозиторий) и централизует запросы (например, спецификации).

Паттерн Facade

Назначение: Предоставляет простой, унифицированный интерфейс к сложной подсистеме, скрывая её внутренние зависимости и сложность.

Пример на C#:

// Сложная подсистема
public class PaymentService { public void Process(Payment p) { /* ... */ } }
public class InventoryService { public void Reserve(Order o) { /* ... */ } }
public class NotificationService { public void SendReceipt(Order o) { /* ... */ } }

// Фасад, упрощающий взаимодействие
public class OrderProcessingFacade
{
    private readonly PaymentService _payment;
    private readonly InventoryService _inventory;
    private readonly NotificationService _notification;

    public OrderProcessingFacade(PaymentService p, InventoryService i, NotificationService n)
    {
        _payment = p; _inventory = i; _notification = n;
    }

    public bool PlaceOrder(Order order)
    {
        // Клиент вызывает один метод вместо трёх
        _inventory.Reserve(order);
        _payment.Process(order.Payment);
        _notification.SendReceipt(order);
        return true;
    }
}

Почему используется: Уменьшает связность клиентского кода с подсистемой, делает код чище и проще для использования.

Ключевые отличия

Аспект Repository Facade
Предмет работы Данные (сущности, агрегаты). Действия и операции сложной подсистемы.
Основная цель Абстракция над источником данных. Упрощение интерфейса к набору классов.
Типичный результат Возвращает доменные объекты или коллекции. Часто выполняет операцию без возврата значения или возвращает упрощённый результат.
Уровень применения Уровень доступа к данным (DAL). Уровень координации сервисов или модулей.

Ответ 18+ 🔞

А, ну ты про Repository и Facade спрашиваешь! Давай разжую, чтобы понятно было, в чём тут разница, а то народ их постоянно путает, как будто это одно и то же. Бред же полный.

Смотри, оба они, конечно, структурные паттерны, но задачи у них — просто пиздец какие разные. Как молоток и плоскогубцы. И тем, и другим можно по лбу стукнуть, но забивать гвозди плоскогубцами — это уже на изобретательность.

Repository (Репозиторий) — это твой личный завхоз по данным.

Его задача — спрятать от тебя всю тупую, однообразную хуйню, связанную с тем, откуда эти данные берутся. База данных там, файлик, удалённый API, или вообще оперативная память для тестов — ему похуй. Ты с ним общаешься на языке твоих бизнес-объектов: «Дай пользователя с ID 5», «Сохрани этот заказ», «Найди всех, кто зарегистрировался после вчера».

// Говоришь ему, что хочешь
public interface IUserRepository
{
    User GetById(int id);
    void Add(User user);
    IEnumerable<User> Find(Expression<Func<User, bool>> predicate);
}

// А как он это делает — твои проблемы кончились. Может, он там SQL-запрос генерит,
// а может, в JSON-файл пишет. Тебе-то что?
public class SqlUserRepository : IUserRepository
{
    private readonly AppDbContext _context;
    public SqlUserRepository(AppDbContext context) => _context = context;

    public User GetById(int id)
    {
        // Вот здесь, внутри, он может делать любую магию с БД.
        // А снаружи — чистый и понятный метод.
        return _context.Users.FirstOrDefault(u => u.Id == id);
    }
}

Зачем он нужен? Ну, во-первых, чтобы не размазывать SQL или вызовы API по всей бизнес-логике. Во-вторых, чтобы можно было в тестах подсунуть «фейковый» репозиторий, который из памяти данные отдаёт, и не ебаться с настоящей базой. Удобно же.


Facade (Фасад) — это твой универсальный пульт от всего этого ебаногого домашнего кинотеатра.

Представь: у тебя куча компонентов — усилитель, проектор, медиаплеер, система затемнения. Чтобы фильм включить, тебе надо нажать кнопок двадцать на пяти разных пультах. Фасад — это одна большая кнопка «Смотреть кино». Нажал — и он сам внутри дергает все эти сервисы в правильном порядке.

// Допустим, у тебя раскидано три сервиса, каждый со своей сложной логикой
public class PaymentService { public void Process(Payment p) { /* ...магия с банками... */ } }
public class InventoryService { public void Reserve(Order o) { /* ...проверка склада... */ } }
public class NotificationService { public void SendReceipt(Order o) { /* ...отправка письма... */ } }

// И ты такой: "Бля, опять мне со всеми тремя общаться?"
// Нахуй это. Делаем фасад.
public class OrderProcessingFacade
{
    private readonly PaymentService _payment;
    private readonly InventoryService _inventory;
    private readonly NotificationService _notification;

    public OrderProcessingFacade(PaymentService p, InventoryService i, NotificationService n)
    {
        _payment = p; _inventory = i; _notification = n;
    }

    // И вот она — та самая одна кнопка!
    public bool PlaceOrder(Order order)
    {
        _inventory.Reserve(order);    // 1. Резервируем товар
        _payment.Process(order.Payment); // 2. Списываем бабки
        _notification.SendReceipt(order); // 3. Шлём чек
        return true; // Всё, доволен, иди отсюда
    }
}

Зачем он нужен? Чтобы клиентский код не превращался в спагетти из вызовов десятка сервисов. Скрыл сложность, уменьшил связность — красота. Главное, не превратить фасад в божественный объект, который знает вообще всё на свете.


Так в чём же, блядь, разница? Коротко и на пальцах:

Критерий Repository Facade
С чем работает С данными (сущности, агрегаты). Его спрашивают: «Где мои данные?». С поведением и операциями сложной подсистемы. Ему говорят: «Сделай вот это».
Основная фишка Абстракция над источником данных (БД, файл, API). Упрощение интерфейса к куче классов или сервисов.
Что возвращает Обычно доменные объекты или их коллекции. Часто просто выполняет действие, может вернуть простой результат (успех/неудача) или ничего.
Где живёт На уровне доступа к данным (DAL), ближе к персистентности. На уровне координации, между бизнес-логикой и сложными подсистемами.

Проще говоря: Repository прячет от тебя как мы получаем/сохраняем данные. Facade прячет от тебя как мы выполняем сложную операцию, разбитую на много шагов.

Если ты путаешь эти два паттерна — у тебя в голове каша, чувак. Иди, перечитай, пока не дойдёт. Это базовое понимание, без которого потом можно так накосячить, что потом всем будет волнение ебать и терпения ноль ебать.