Суть: Гарантирует существование только одного экземпляра класса
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 abstract class Document
{
public abstract void CreatePages();
}
public class Resume : Document
{
public override void CreatePages()
{
Pages.Add(new SkillsPage());
}
}
Применение: Плагины, кросс-платформенные UI
Суть: Преобразует интерфейс класса в другой интерфейс, ожидаемый клиентом
public interface ITarget
{
string GetRequest();
}
public class Adaptee
{
public string GetSpecificRequest() => "Specific request";
}
public class Adapter : ITarget
{
private readonly Adaptee _adaptee;
public Adapter(Adaptee adaptee) => _adaptee = adaptee;
public string GetRequest() => _adaptee.GetSpecificRequest();
}
Применение: Интеграция legacy-кода, работа со сторонними библиотеками
Суть: Объединяет объекты в древовидные структуры
public interface IGraphic
{
void Draw();
}
public class Circle : IGraphic { /*...*/ }
public class GraphicGroup : IGraphic
{
private readonly List<IGraphic> _children = new();
public void Add(IGraphic graphic) => _children.Add(graphic);
public void Draw() => _children.ForEach(c => c.Draw());
}
Применение: UI-фреймворки, файловые системы
Суть: Определяет зависимость "один-ко-многим" между объектами
public interface IObserver
{
void Update(ISubject subject);
}
public class ConcreteObserver : IObserver
{
public void Update(ISubject subject) { /*...*/ }
}
public class Subject : ISubject
{
private readonly List<IObserver> _observers = new();
public void Attach(IObserver observer) => _observers.Add(observer);
public void Notify() => _observers.ForEach(o => o.Update(this));
}
Применение: Событийные модели, MVC
Суть: Определяет семейство алгоритмов, инкапсулирует каждый из них
public interface ISortStrategy
{
void Sort(List<int> data);
}
public class QuickSort : ISortStrategy { /*...*/ }
public class MergeSort : ISortStrategy { /*...*/ }
public class Sorter
{
private ISortStrategy _strategy;
public void SetStrategy(ISortStrategy strategy) => _strategy = strategy;
public void Sort(List<int> data) => _strategy?.Sort(data);
}
Применение: Платежные системы, алгоритмы обработки данных
Суть: Абстрагирует доступ к данным
public interface IRepository<T>
{
T GetById(int id);
void Add(T entity);
}
public class UserRepository : IRepository<User>
{
public User GetById(int id) { /*...*/ }
public void Add(User entity) { /*...*/ }
}
Суть: Разделение операций чтения и записи
public interface ICommandHandler<in TCommand>
{
Task Handle(TCommand command);
}
public class CreateUserCommandHandler : ICommandHandler<CreateUserCommand>
{
public Task Handle(CreateUserCommand command) { /*...*/ }
}
Суть: Разделение процессов генерации и обработки данных
BlockingCollection<Item> _queue = new();
// Producer
Task.Run(() =>
{
while (true)
_queue.Add(GenerateItem());
});
// Consumer
Task.Run(() =>
{
foreach (var item in _queue.GetConsumingEnumerable())
ProcessItem(item);
});
паттерны - это проверенные решения распространенных проблем проектирования. Их правильное применение значительно улучшает качество кода, но слепое следование паттернам без понимания контекста может усложнить систему. Важно выбирать паттерны осознанно, исходя из конкретных требований проекта.