Паттерны проектирования тесно связаны с SOLID-принципами — основой правильной объектно-ориентированной архитектуры. Понимание этой связи помогает применять паттерны осознанно, усиливая сильные стороны ООП.
| Принцип | Проблема | Паттерны, которые помогают |
|---|---|---|
| SRP | Класс берёт на себя слишком много обязанностей | Facade, Decorator, Command, Observer |
| OCP | Изменения требуют правки существующего кода | Strategy, Template Method, Chain of Responsibility |
| LSP | Наследники нарушают поведение базового класса | State, Bridge — позволяют изолировать вариации поведения |
| ISP | Интерфейсы перегружены методами, которые не нужны клиентам | Adapter, Proxy, Mediator |
| DIP | Класс зависит от конкретных реализаций, а не от абстракций | Factory Method, Abstract Factory, Dependency Injection |
Strategy идеально реализует принцип открытости/закрытости: можно добавлять новые алгоритмы без изменения существующего кода.
// Интерфейс стратегии
public interface IPaymentStrategy { void Pay(decimal amount); }
// Конкретные реализации
public class CardPayment : IPaymentStrategy { public void Pay(decimal amount) => Console.WriteLine("Картой"); }
public class CryptoPayment : IPaymentStrategy { public void Pay(decimal amount) => Console.WriteLine("Криптой"); }
// Контекст
public class PaymentService
{
private IPaymentStrategy _strategy;
public void SetStrategy(IPaymentStrategy strategy) => _strategy = strategy;
public void Pay(decimal amount) => _strategy.Pay(amount);
}
Decorator помогает не нарушать принцип SRP, добавляя новое поведение без изменения базового класса.
// Базовый интерфейс
public interface INotifier { void Send(string message); }
// Основной класс
public class EmailNotifier : INotifier
{
public void Send(string message) => Console.WriteLine($"Email: {message}");
}
// Декоратор
public class SmsDecorator : INotifier
{
private INotifier _inner;
public SmsDecorator(INotifier inner) => _inner = inner;
public void Send(string message)
{
_inner.Send(message);
Console.WriteLine($"SMS: {message}");
}
}
Factory Method позволяет зависеть от абстракции, а не от конкретных классов.
public abstract class LoggerFactory
{
public abstract ILogger CreateLogger();
}
public class FileLoggerFactory : LoggerFactory
{
public override ILogger CreateLogger() => new FileLogger();
} Mediator реализует принцип разделения интерфейсов, уменьшая количество прямых зависимостей между классами.
public interface IMediator
{
void Notify(object sender, string ev);
} Observer разделяет ответственность: источник данных не знает, кто его слушает. Также можно добавлять новых наблюдателей без изменения субъекта.
public interface IObserver { void Update(string message); }
public interface ISubject { void Attach(IObserver o); void Notify(string msg); } Паттерны — это не замена SOLID, а его практическое воплощение. Каждый из них помогает реализовать конкретный принцип или устранить типичное нарушение: Decorator поддерживает SRP, Strategy — OCP, Factory Method — DIP. Чем глубже вы понимаете SOLID, тем точнее выбираете паттерны — и наоборот.