Паттерны GoF — это 23 классических паттерна проектирования, описанных в книге "Design Patterns: Elements of Reusable Object-Oriented Software". Они делятся на три категории: порождающие, структурные и поведенческие. Вот наиболее часто используемые из них в C# разработке:
Гарантирует, что у класса есть только один экземпляр.
public sealed class Singleton
{
private static Singleton _instance;
private static readonly object _lock = new object();
private Singleton() { }
public static Singleton Instance
{
get
{
lock (_lock)
{
return _instance ??= new Singleton();
}
}
}
}
Определяет интерфейс для создания объекта, но оставляет подклассам решение о том, какой класс инстанцировать.
public interface IProduct {}
public class ConcreteProduct : IProduct {}
public abstract class Creator
{
public abstract IProduct FactoryMethod();
}
public class ConcreteCreator : Creator
{
public override IProduct FactoryMethod() => new ConcreteProduct();
}
Позволяет объектам с несовместимыми интерфейсами работать вместе.
public interface ITarget { void Request(); }
public class Adaptee { public void SpecificRequest() {} }
public class Adapter : ITarget
{
private readonly Adaptee _adaptee;
public Adapter(Adaptee adaptee) => _adaptee = adaptee;
public void Request() => _adaptee.SpecificRequest();
}
Динамически добавляет объекту новые обязанности.
public interface IComponent { void Operation(); }
public class ConcreteComponent : IComponent
{
public void Operation() => Console.Write("ConcreteComponent");
}
public class Decorator : IComponent
{
private readonly IComponent _component;
public Decorator(IComponent component) => _component = component;
public virtual void Operation() => _component.Operation();
}
public class ConcreteDecorator : Decorator
{
public ConcreteDecorator(IComponent component) : base(component) {}
public override void Operation()
{
base.Operation();
Console.Write(" + Decorator");
}
}
Определяет зависимость "один-ко-многим" между объектами.
public interface IObserver { void Update(); }
public interface ISubject
{
void Attach(IObserver observer);
void Detach(IObserver observer);
void Notify();
}
public class ConcreteSubject : ISubject
{
private readonly List<IObserver> _observers = new();
public void Attach(IObserver observer) => _observers.Add(observer);
public void Detach(IObserver observer) => _observers.Remove(observer);
public void Notify() => _observers.ForEach(o => o.Update());
}
Определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми.
public interface ISortStrategy
{
void Sort(List<int> list);
}
public class QuickSort : ISortStrategy
{
public void Sort(List<int> list) => Console.WriteLine("QuickSort");
}
public class Context
{
private ISortStrategy _strategy;
public void SetStrategy(ISortStrategy strategy) => _strategy = strategy;
public void ExecuteSort(List<int> list) => _strategy.Sort(list);
}
HttpContext.Current
в ASP.NETList<T>.Sort(IComparer<T>)
Stream
и его декораторы (BufferedStream
, CryptoStream
)паттерны GoF предоставляют проверенные решения распространенных проблем проектирования ПО. В C# они часто реализуются с помощью интерфейсов, абстрактных классов и делегатов. Правильное применение паттернов делает код более гибким, расширяемым и поддерживаемым, но важно избегать их избыточного использования там, где можно обойтись более простыми решениями.