Какие паттерны проектирования GOF использовал?
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Распространённые паттерны проектирования GOF в C# Backend‑разработке
За годы работы с C# и .NET я активно применял классические паттерны из каталога Gang of Four (GOF), адаптируя их к особенностям платформы и современных архитектур. Вот наиболее часто используемые категории и примеры их реализации.
Порождающие паттерны (Creational)
Эти паттерны отвечают за создание объектов, обеспечивая гибкость и инкапсуляцию процесса.
-
Singleton (Одиночка) — несмотря на известные проблемы с тестированием, применяется для создания единственного экземпляра сервиса, который должен быть глобально доступен (например, логгер, кэш в памяти, конфигурация приложения). В современных .NET‑приложениях его роль часто берут на себя DI‑контейнеры, регистрирующие сервисы как
AddSingleton.public sealed class AppConfig { private static readonly Lazy<AppConfig> _instance = new Lazy<AppConfig>(() => new AppConfig()); public static AppConfig Instance => _instance.Value; private AppConfig() { } // Приватный конструктор public string ConnectionString { get; set; } } -
Factory Method (Фабричный метод) — используется, когда создание объекта должно делегироваться подклассам. Часто встречается в библиотеках, например, в
DbContextEntity Framework Core, где фабричный методOnConfiguringпозволяет настроить подключение к БД.public abstract class DocumentProcessor { // Фабричный метод protected abstract IDocumentParser CreateParser(); public void Process() { var parser = CreateParser(); // Создание через наследника parser.Parse(); } } public class PdfProcessor : DocumentProcessor { protected override IDocumentParser CreateParser() => new PdfParser(); } -
Abstract Factory (Абстрактная фабрика) — полезен для создания семейств взаимосвязанных объектов без привязки к конкретным классам. Пример — абстракция над разными поставщиками данных (SQL, NoSQL).
public interface IDbFactory { IConnection CreateConnection(); ICommand CreateCommand(); } public class SqlServerFactory : IDbFactory { public IConnection CreateConnection() => new SqlConnection(); public ICommand CreateCommand() => new SqlCommand(); } -
Builder (Строитель) — идеален для пошагового создания сложных объектов с множеством опциональных параметров. Широко применяется для конфигурации (
HostBuilder,WebApplicationBuilderв ASP.NET Core) или построения сложных DTO/запросов.public class QueryBuilder { private string _select = "*"; private string _where = ""; public QueryBuilder Select(string fields) { _select = fields; return this; } public QueryBuilder Where(string condition) { _where = $" WHERE {condition}"; return this; } public string Build() => $"SELECT {_select} FROM Table{_where}"; } // Использование var query = new QueryBuilder().Select("Id, Name").Where("Age > 18").Build();
Структурные паттерны (Structural)
Паттерны этой группы отвечают за композицию классов и объектов.
-
Adapter (Адаптер) — постоянно используется для интеграции сторонних библиотек или legacy‑кода, преобразуя их интерфейс в ожидаемый клиентом. Например, адаптер для старой системы логирования под новый интерфейс
ILogger.public interface IModernLogger { void LogInfo(string message); } public class LegacyLoggerAdapter : IModernLogger { private readonly LegacyLogger _legacyLogger; public LegacyLoggerAdapter(LegacyLogger logger) => _legacyLogger = logger; public void LogInfo(string message) => _legacyLogger.WriteLog($"INFO: {message}"); } -
Decorator (Декоратор) — один из ключевых паттернов для добавления поведения объектам без изменения их класса. В C# часто реализуется через композицию и внедрение зависимостей. Классический пример — добавление кэширования, логирования или валидации к сервису.
public interface IDataService { string GetData(); } public class CacheDecorator : IDataService { private readonly IDataService _innerService; private readonly ICache _cache; public CacheDecorator(IDataService service, ICache cache) { _innerService = service; _cache = cache; } public string GetData() { var key = "data_key"; if (_cache.TryGet(key, out string data)) return data; data = _innerService.GetData(); // Вызов основного сервиса _cache.Set(key, data); return data; } } -
Facade (Фасад) — упрощает работу со сложными подсистемами, предоставляя единый удобный интерфейс. Типичный пример — сервис для работы с заказом (
OrderService), который внутри координирует вызовыInventoryService,PaymentServiceиShippingService.public class OrderFacade { private readonly IInventoryService _inventory; private readonly IPaymentService _payment; private readonly IShippingService _shipping; public OrderFacade(IInventoryService inv, IPaymentService pay, IShippingService ship) { _inventory = inv; _payment = pay; _shipping = ship; } public bool PlaceOrder(Order order) { if (!_inventory.CheckStock(order)) return false; if (!_payment.ProcessPayment(order)) return false; _shipping.ScheduleDelivery(order); return true; } }
Поведенческие паттерны (Behavioral)
Эти паттерны определяют взаимодействие между объектами и распределение ответственности.
-
Strategy (Стратегия) — чрезвычайно полезен для инкапсуляции алгоритмов и возможности их динамической замены. Часто применяется для различных способов вычисления (
IDiscountStrategy), валидации (IValidationStrategy) или сериализации (ISerializer).public interface ISortStrategy<T> { IEnumerable<T> Sort(IEnumerable<T> data); } public class QuickSortStrategy<T> : ISortStrategy<T> { /* реализация */ } public class MergeSortStrategy<T> : ISortStrategy<T> { /* реализация */ } public class Sorter<T> { private ISortStrategy<T> _strategy; public void SetStrategy(ISortStrategy<T> strategy) => _strategy = strategy; public IEnumerable<T> ExecuteSort(IEnumerable<T> data) => _strategy.Sort(data); } -
Observer (Наблюдатель) — фундаментальный паттерн для реализации событийной модели. В C# он встроен в язык через механизм событий (events) и делегатов. Широко используется для уведомлений об изменениях состояния (например, в паттерне MVVM или для доменных событий).
public class OrderProcessor { public event EventHandler<OrderEventArgs> OrderProcessed; // Объявление события public void Process(Order order) { // Логика обработки... OnOrderProcessed(new OrderEventArgs(order)); } protected virtual void OnOrderProcessed(OrderEventArgs e) => OrderProcessed?.Invoke(this, e); // Вызов события } -
Command (Команда) — инкапсулирует запрос как объект, что позволяет параметризовать клиентов различными запросами, ставить их в очередь, логировать и поддерживать отмену операций. Применяется в системах с транзакциями, job‑очередях или для реализации undo/redo.
public interface ICommand { void Execute(); void Undo(); } public class UpdateUserCommand : ICommand { private readonly UserService _service; private User _oldState, _newState; public UpdateUserCommand(UserService service, User newState) { _service = service; _newState = newState; } public void Execute() { _oldState = _service.GetUser(_newState.Id); _service.Update(_newState); } public void Undo() => _service.Update(_oldState); }
Заключение
Выбор паттерна всегда определяется конкретной задачей и контекстом. В современных ASP.NET Core‑приложениях многие проблемы, которые раньше решались «вручную» через GOF‑паттерны, теперь элегантно решаются встроенными механизмами: внедрение зависимостей (DI) заменяет фабрики и упрощает декораторы, Middleware‑пайплайн является разновидностью Chain of Responsibility, а система событий (EventBus) часто реализует Observer или Mediator.
Однако глубокое понимание этих классических паттернов остаётся критически важным. Оно позволяет:
- Осознанно использовать встроенные возможности фреймворка.
- Эффективно проектировать собственную бизнес‑логику.
- Читать и понимать архитектуру сторонних библиотек.
- Применять гибридные решения, комбинируя паттерны для решения сложных задач.
Таким образом, GOF‑паттерны — это не набор догм, а словарь для описания и решения архитектурных проблем, который остаётся актуальным даже в контексте современных фреймворков и парадигм.