Какие знаешь структурные паттерны проектирования?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Структурные паттерны проектирования в C#
Структурные паттерны — это шаблоны проектирования, которые упрощают построение сложных объектных структур за счёт композиции классов и объектов. Они помогают обеспечить гибкость и эффективность системы, управляя отношениями между сущностями. Вот основные структурные паттерны, которые я применяю в C# Backend-разработке:
1. Адаптер (Adapter)
Паттерн Адаптер позволяет объектам с несовместимыми интерфейсами работать вместе. Он оборачивает несовместимый объект и предоставляет совместимый интерфейс. В C# часто используется для интеграции сторонних библиотек или устаревшего кода.
// Целевой интерфейс
public interface ILogger
{
void Log(string message);
}
// Адаптируемый класс
public class FileLoggerLegacy
{
public void WriteToFile(string text)
{
File.WriteAllText("log.txt", text);
}
}
// Адаптер
public class FileLoggerAdapter : ILogger
{
private readonly FileLoggerLegacy _legacyLogger;
public FileLoggerAdapter(FileLoggerLegacy legacyLogger)
{
_legacyLogger = legacyLogger;
}
public void Log(string message)
{
_legacyLogger.WriteToFile($"[{DateTime.Now}] {message}");
}
}
// Использование
var legacyLogger = new FileLoggerLegacy();
ILogger logger = new FileLoggerAdapter(legacyLogger);
logger.Log("Привет, мир!");
2. Мост (Bridge)
Паттерн Мост разделяет абстракцию и реализацию, позволяя им изменяться независимо. Это особенно полезно для поддержки множественных платформ или реализаций.
// Реализация
public interface IRenderer
{
void RenderCircle(float radius);
}
public class VectorRenderer : IRenderer
{
public void RenderCircle(float radius)
{
Console.WriteLine($"Рисуем круг радиусом {radius} в векторном формате");
}
}
public class RasterRenderer : IRenderer
{
public void RenderCircle(float radius)
{
Console.WriteLine($"Рисуем пиксели круга радиусом {radius}");
}
}
// Абстракция
public abstract class Shape
{
protected IRenderer renderer;
protected Shape(IRenderer renderer)
{
this.renderer = renderer;
}
public abstract void Draw();
}
public class Circle : Shape
{
private float radius;
public Circle(float radius, IRenderer renderer) : base(renderer)
{
this.radius = radius;
}
public override void Draw()
{
renderer.RenderCircle(radius);
}
}
3. Компоновщик (Composite)
Паттерн Компоновщик позволяет сгруппировать объекты в древовидные структуры и работать с ними как с единым объектом. Идеально подходит для иерархических данных.
public interface IGraphic
{
void Draw();
void Move(int x, int y);
}
public class Circle : IGraphic
{
public void Draw() => Console.WriteLine("Рисуем круг");
public void Move(int x, int y) => Console.WriteLine($"Перемещаем круг на ({x},{y})");
}
public class CompositeGraphic : IGraphic
{
private List<IGraphic> _children = new List<IGraphic>();
public void Add(IGraphic graphic) => _children.Add(graphic);
public void Remove(IGraphic graphic) => _children.Remove(graphic);
public void Draw()
{
foreach (var child in _children)
child.Draw();
}
public void Move(int x, int y)
{
foreach (var child in _children)
child.Move(x, y);
}
}
4. Декоратор (Decorator)
Паттерн Декоратор динамически добавляет объекту новые обязанности, предоставляя гибкую альтернативу наследованию. В ASP.NET Core активно используется в Middleware.
public interface INotifier
{
void Send(string message);
}
public class EmailNotifier : INotifier
{
public void Send(string message)
{
Console.WriteLine($"Отправка email: {message}");
}
}
public abstract class NotifierDecorator : INotifier
{
protected INotifier _notifier;
protected NotifierDecorator(INotifier notifier)
{
_notifier = notifier;
}
public virtual void Send(string message)
{
_notifier.Send(message);
}
}
public class SMSNotifierDecorator : NotifierDecorator
{
public SMSNotifierDecorator(INotifier notifier) : base(notifier) {}
public override void Send(string message)
{
base.Send(message);
Console.WriteLine($"Отправка SMS: {message}");
}
}
5. Фасад (Facade)
Паттерн Фасад предоставляет упрощённый интерфейс к сложной подсистеме, скрывая её внутреннюю сложность.
// Сложная подсистема
public class DatabaseService
{
public void Connect() => Console.WriteLine("Подключение к БД");
public void Query(string sql) => Console.WriteLine($"Выполнение запроса: {sql}");
}
public class CacheService
{
public void Set(string key, object value) => Console.WriteLine($"Кэширование: {key}");
public object Get(string key) => null;
}
// Фасад
public class DataAccessFacade
{
private DatabaseService _db;
private CacheService _cache;
public DataAccessFacade()
{
_db = new DatabaseService();
_cache = new CacheService();
}
public object GetData(string key)
{
var data = _cache.Get(key);
if (data == null)
{
_db.Connect();
_db.Query($"SELECT * FROM data WHERE key='{key}'");
data = new object();
_cache.Set(key, data);
}
return data;
}
}
6. Приспособленец (Flyweight)
Паттерн Приспособленец позволяет эффективно поддерживать множество мелких объектов, разделяя общее состояние между ними. Экономит память за счёт кэширования.
public class FlyweightFactory
{
private Dictionary<string, IFlyweight> _flyweights = new();
public IFlyweight GetFlyweight(string key)
{
if (!_flyweights.ContainsKey(key))
_flyweights[key] = new ConcreteFlyweight(key);
return _flyweights[key];
}
}
public interface IFlyweight
{
void Operation(string extrinsicState);
}
7. Заместитель (Proxy)
Паттерн Заместитель предоставляет суррогатный объект, контролирующий доступ к другому объекту. Используется для ленивой инициализации, кэширования, контроля доступа.
public interface ISubject
{
void Request();
}
public class RealSubject : ISubject
{
public void Request()
{
Console.WriteLine("Выполнение реального запроса...");
}
}
public class Proxy : ISubject
{
private RealSubject _realSubject;
public void Request()
{
if (_realSubject == null)
_realSubject = new RealSubject();
Console.WriteLine("Проверка доступа...");
_realSubject.Request();
Console.WriteLine("Логирование запроса...");
}
}
Практическое применение в Backend-разработке
В C# Backend-разработке структурные паттерны решают критически важные задачи:
- Адаптеры для интеграции с внешними API и устаревшими системами
- Декораторы в Middleware ASP.NET Core для добавления функциональности (аутентификация, логирование, кэширование)
- Фасады для упрощения работы со сложными модулями (ORM, кэширование, очереди сообщений)
- Прокси для реализации ленивой загрузки данных, кэширования и контроля доступа
- Компоновщики для построения иерархических структур (меню, разрешения, организационные структуры)
Наиболее часто я использую Декоратор (для Middleware), Адаптер (для интеграций) и Фасад (для упрощения сложных подсистем). Правильное применение структурных паттернов позволяет создавать гибкие, поддерживаемые и масштабируемые backend-системы на C#.