C# | Вопросы собесов
5.1K subscribers
35 photos
1 file
983 links
Download Telegram
🤔 Что такое ref & out?

ref позволяет передавать переменные по ссылке, сохраняя изменения, а out требует инициализации переменной в методе.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Для чего используется dependency injection?

Dependency Injection (DI) используется для управления зависимостями объектов в приложении. Это шаблон проектирования, который помогает реализовать принцип инверсии зависимостей (DIP) из SOLID-принципов. DI делает код более модульным, тестируемым и гибким. Рассмотрим ключевые цели и преимущества использования Dependency Injection.

🚩Основные цели

🟠Снижение связанности кода
DI позволяет классу получить свои зависимости извне, вместо того чтобы создавать их самостоятельно. Это снижает связанность кода и упрощает его сопровождение и изменение.
public class UserService
{
private readonly IUserRepository _userRepository;

// Зависимость внедряется через конструктор
public UserService(IUserRepository userRepository)
{
_userRepository = userRepository;
}

public void CreateUser(string name)
{
_userRepository.AddUser(name);
}
}


🟠Улучшение тестируемости
DI упрощает создание юнит-тестов, так как зависимости могут быть заменены моками или стабыми. Это позволяет изолировать тестируемый код и тестировать его независимо от реальных зависимостей.
[Test]
public void CreateUser_ShouldCallAddUser()
{
var mockRepository = new Mock<IUserRepository>();
var userService = new UserService(mockRepository.Object);

userService.CreateUser("John Doe");

mockRepository.Verify(r => r.AddUser("John Doe"), Times.Once);
}


🟠Повышение гибкости и расширяемости
DI позволяет легко заменять реализации зависимостей, что упрощает изменение поведения приложения без необходимости модификации кода, использующего эти зависимости.
var services = new ServiceCollection();
services.AddTransient<IUserRepository, UserRepository>();
services.AddTransient<UserService>();

var serviceProvider = services.BuildServiceProvider();
var userService = serviceProvider.GetService<UserService>();


🟠Управление жизненным циклом объектов
DI-контейнеры позволяют управлять жизненным циклом зависимостей, обеспечивая контроль над созданием, временем жизни и удалением объектов.
services.AddSingleton<IConfiguration>(new Configuration());
services.AddScoped<IDatabaseContext, DatabaseContext>();
services.AddTransient<IUserRepository, UserRepository>();


🚩Пример использования Dependency Injection

Определение интерфейсов и реализаций
public interface IMessageService
{
void SendMessage(string message);
}

public class EmailService : IMessageService
{
public void SendMessage(string message)
{
Console.WriteLine($"Email sent: {message}");
}
}

public class SmsService : IMessageService
{
public void SendMessage(string message)
{
Console.WriteLine($"SMS sent: {message}");
}
}


Внедрение зависимостей через конструктор
public class NotificationController
{
private readonly IMessageService _messageService;

public NotificationController(IMessageService messageService)
{
_messageService = messageService;
}

public void Notify(string message)
{
_messageService.SendMessage(message);
}
}


Настройка DI-контейнера
var services = new ServiceCollection();
services.AddTransient<IMessageService, EmailService>(); // или SmsService
services.AddTransient<NotificationController>();

var serviceProvider = services.BuildServiceProvider();
var controller = serviceProvider.GetService<NotificationController>();

controller.Notify("Hello World!");


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Как работает Entity Framework?

EF преобразует данные из базы в объекты .NET, поддерживает LINQ-запросы и управление миграциями.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🔥1
🤔 Что такое связанность и связность?

🚩Связанность (Cohesion)

Описывает, насколько элементы внутри модуля связаны между собой. Высокая связанность (хорошая) означает, что элементы модуля работают над одной задачей.
public class FileProcessor
{
public void ProcessFile(string filePath)
{
ReadFile(filePath);
ParseData();
SaveResults();
}

private void ReadFile(string filePath) { /* чтение файла */ }
private void ParseData() { /* парсинг данных */ }
private void SaveResults() { /* сохранение результатов */ }
}


🚩Связность (Coupling)

Описывает зависимость между модулями. Низкая связность (хорошая) означает, что модули минимально зависят друг от друга.
public interface IDataService
{
void SaveData(string data);
}

public class DataService : IDataService
{
public void SaveData(string data) { /* сохранение данных */ }
}

public class Processor
{
private readonly IDataService _dataService;

public Processor(IDataService dataService)
{
_dataService = dataService;
}

public void Process(string data)
{
_dataService.SaveData(data);
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍72🤔1
🤔 Что такое инкапсуляция?

Инкапсуляция скрывает детали реализации объекта, предоставляя доступ через публичные методы для защиты данных.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🤔4
🤔 Что такое тесные связи между объектами?

Это ситуация, когда один объект сильно зависит от другого, что затрудняет их независимое изменение и тестирование. Например, если изменение в одном объекте требует изменений в другом объекте, то связь между ними считается тесной.
public class DataService
{
public void SaveData(string data) { /* Сохранение данных */ }
}

public class Processor
{
private DataService _dataService = new DataService();

public void Process(string data)
{
_dataService.SaveData(data);
}
}


Уменьшенная связность
public interface IDataService
{
void SaveData(string data);
}

public class DataService : IDataService
{
public void SaveData(string data) { /* Сохранение данных */ }
}

public class Processor
{
private readonly IDataService _dataService;

public Processor(IDataService dataService)
{
_dataService = dataService;
}

public void Process(string data)
{
_dataService.SaveData(data);
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤔 Как сделать миграцию методов?

Миграция методов подразумевает их перемещение или переработку между классами, что требует анализа текущей логики и всех мест, где методы используются. Следует обновить ссылки, провести рефакторинг кода и написать тесты для проверки функциональности после изменений. Это помогает минимизировать риски нарушения работы системы.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Что из себя представляет абстракция?

Это один из ключевых принципов объектно-ориентированного программирования (ООП), который позволяет выделять важные характеристики объекта, игнорируя несущественные детали. Абстракция упрощает сложные системы, предоставляя только те аспекты, которые необходимы для выполнения конкретной задачи.

🚩Аспекты

🟠Скрытие деталей реализации
Абстракция позволяет скрыть сложные детали реализации и предоставлять простой интерфейс для взаимодействия с объектом.
public abstract class Animal
{
public abstract void MakeSound();
}

public class Dog : Animal
{
public override void MakeSound()
{
Console.WriteLine("Bark");
}
}


🟠Определение интерфейсов и абстрактных классов
Интерфейсы и абстрактные классы являются основными инструментами абстракции в C#. Интерфейсы определяют контракт, который должен быть реализован классами, а абстрактные классы могут содержать как реализацию, так и абстрактные методы.
public interface IShape
{
double GetArea();
}

public class Circle : IShape
{
public double Radius { get; set; }
public double GetArea()
{
return Math.PI * Radius * Radius;
}
}

public abstract class Vehicle
{
public abstract void Move();
}

public class Car : Vehicle
{
public override void Move()
{
Console.WriteLine("Car is moving");
}
}


🚩Сокрытие ненужных деталей

Абстракция помогает пользователям взаимодействовать с объектом через его публичный интерфейс, не беспокоясь о внутренних деталях.
public class CoffeeMachine
{
public void MakeCoffee()
{
HeatWater();
BrewCoffee();
PourCoffee();
}

private void HeatWater() { /* Подогрев воды */ }
private void BrewCoffee() { /* Заваривание кофе */ }
private void PourCoffee() { /* Наливание кофе */ }
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Что такое интерфейс?

Интерфейс — это контракт, который определяет набор методов и свойств, которые класс обязан реализовать. В отличие от классов, интерфейсы не содержат реализации, что позволяет разрабатывать гибкие и расширяемые архитектуры, где конкретное поведение зависит от реализации.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
🤔 Если не будем использовать абстракции, что может произойти?

🟠Сложность и запутанность кода
Без абстракций код станет более сложным и трудным для понимания, так как все детали реализации будут видны пользователю. Это затруднит работу с кодом, особенно в больших проектах.

🟠Повышенная связанность
Классы и модули будут сильно зависеть друг от друга, что приведет к высокой связанности. Это затруднит изменения и рефакторинг кода, так как любое изменение в одном месте потребует изменений в других местах.

🟠Низкая повторная использование
Без абстракций код будет менее модульным и его будет трудно повторно использовать в других проектах или частях проекта.

🟠Сложность тестирования
Код без абстракций труднее тестировать, так как сложно изолировать отдельные части системы для юнит-тестирования. Это может привести к большему количеству ошибок и дефектов в коде.

🟠Затрудненное сопровождение
Код станет труднее поддерживать и сопровождать, так как его будет сложно изменять, исправлять ошибки или добавлять новые функции без риска сломать существующую функциональность.

🚩Примеры проблем

Без абстракции
public class UserService
{
public void RegisterUser(string username, string password)
{
// Логика регистрации пользователя
var db = new Database();
db.SaveUser(username, password);
}
}

public class Database
{
public void SaveUser(string username, string password)
{
// Сохранение пользователя в базу данных
}
}


С использованием абстракции
public interface IUserRepository
{
void SaveUser(string username, string password);
}

public class UserService
{
private readonly IUserRepository _userRepository;

public UserService(IUserRepository userRepository)
{
_userRepository = userRepository;
}

public void RegisterUser(string username, string password)
{
// Логика регистрации пользователя
_userRepository.SaveUser(username, password);
}
}

public class Database : IUserRepository
{
public void SaveUser(string username, string password)
{
// Сохранение пользователя в базу данных
}
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
🤔 Что такое SignalR?

SignalR — это библиотека от Microsoft для обеспечения двусторонней связи в реальном времени между клиентом и сервером. Она использует протоколы, такие как WebSockets, для высокой производительности, а в случае их недоступности — другие технологии, например, long polling. SignalR упрощает разработку чатов, уведомлений и других динамичных приложений.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥21
🤔 Для чего нужен Dependency injection?

Это паттерн проектирования, который используется для внедрения зависимостей объектов. Он помогает улучшить модульность, тестируемость и гибкость кода. Рассмотрим, зачем нужен Dependency Injection и какие преимущества он приносит.

🚩Основные цели и преимущества

🟠Снижение связанности кода
DI позволяет классам не зависеть от конкретных реализаций своих зависимостей. Вместо этого зависимости передаются извне, обычно через конструкторы, методы или свойства. Это уменьшает связанность и делает код более модульным.
public class UserService
{
private readonly IUserRepository _userRepository;

public UserService(IUserRepository userRepository)
{
_userRepository = userRepository;
}

public void RegisterUser(string username, string password)
{
_userRepository.SaveUser(username, password);
}
}


🟠Улучшение тестируемости
DI упрощает создание юнит-тестов, так как зависимости могут быть заменены на моки или стабы. Это позволяет изолировать тестируемый код и тестировать его без зависимости от реальных объектов.
[Test]
public void RegisterUser_ShouldCallSaveUser()
{
var mockRepository = new Mock<IUserRepository>();
var userService = new UserService(mockRepository.Object);

userService.RegisterUser("testuser", "password");

mockRepository.Verify(r => r.SaveUser("testuser", "password"), Times.Once);
}


🟠Повышение гибкости и расширяемости
DI позволяет легко заменять реализации зависимостей, что упрощает изменение поведения приложения без необходимости модифицировать код, использующий эти зависимости.
var services = new ServiceCollection();
services.AddTransient<IUserRepository, SqlUserRepository>(); // или MemoryUserRepository
services.AddTransient<UserService>();

var serviceProvider = services.BuildServiceProvider();
var userService = serviceProvider.GetService<UserService>();


🟠Управление жизненным циклом объектов
DI-контейнеры управляют созданием, временем жизни и удалением объектов, что позволяет лучше контролировать ресурсы и повышает эффективность использования памяти.
services.AddSingleton<IConfiguration>(new Configuration());
services.AddScoped<IDatabaseContext, DatabaseContext>();
services.AddTransient<IUserRepository, UserRepository>();


🚩Пример использования

1⃣Определение интерфейсов и реализаций
public interface IMessageService
{
void SendMessage(string message);
}

public class EmailService : IMessageService
{
public void SendMessage(string message)
{
Console.WriteLine($"Email sent: {message}");
}
}

public class SmsService : IMessageService
{
public void SendMessage(string message)
{
Console.WriteLine($"SMS sent: {message}");
}
}


2⃣Внедрение зависимостей через конструктор
public class NotificationController
{
private readonly IMessageService _messageService;

public NotificationController(IMessageService messageService)
{
_messageService = messageService;
}

public void Notify(string message)
{
_messageService.SendMessage(message);
}
}


3⃣Настройка DI-контейнера
var services = new ServiceCollection();
services.AddTransient<IMessageService, EmailService>(); // или SmsService
services.AddTransient<NotificationController>();

var serviceProvider = services.BuildServiceProvider();
var controller = serviceProvider.GetService<NotificationController>();

controller.Notify("Hello World!");


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍2🔥1
🤔 Какие механизмы позволяют не нарушать принцип dependency inversion?

Для соблюдения принципа dependency inversion используются интерфейсы и абстракции, которые позволяют код зависеть от общего поведения, а не от конкретных реализаций. Также помогают фабрики (Factories) для создания объектов и DI-контейнеры (Dependency Injection), которые управляют зависимостями и их внедрением.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 Что такое Idisposable?

Это интерфейс в .NET, который предоставляет механизм для высвобождения неуправляемых ресурсов. Он содержит один метод Dispose, который должен быть реализован классами, использующими неуправляемые ресурсы, такие как файловые дескрипторы, соединения с базами данных или ресурсы ОС.

🚩Основная цель

Это освобождение ресурсов, которые не управляются средой CLR (Common Language Runtime). Такие ресурсы не могут быть автоматически освобождены сборщиком мусора, поэтому необходимо явно управлять их жизненным циклом.

🚩Метод `Dispose`

Метод Dispose должен быть реализован для освобождения неуправляемых ресурсов. В классе, реализующем IDisposable, метод Dispose вызывается для выполнения любых необходимых очисток.

🚩Примеры использования

Реализация IDisposable для класса с неуправляемыми ресурсами
public class ResourceHolder : IDisposable
{
private bool _disposed = false; // Для отслеживания вызова Dispose

// Метод для освобождения ресурсов
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this); // Подавляет финализацию
}

// Защищенный метод для освобождения ресурсов
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// Освобождаем управляемые ресурсы
}

// Освобождаем неуправляемые ресурсы
_disposed = true;
}
}

~ResourceHolder()
{
Dispose(false);
}
}


Использование using для автоматического вызова Dispose
public void UseResource()
{
using (var resourceHolder = new ResourceHolder())
{
// Работа с ресурсом
} // Здесь автоматически вызовется Dispose
}


Ставь
👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8
🤔 Что такое Action Executor и Action Executing?

ActionExecutor — это компонент, который отвечает за выполнение действия, обычно связанного с бизнес-логикой приложения. ActionExecuting запускается перед выполнением действия и используется для проверки условий, логирования или предварительной настройки. Эти механизмы позволяют управлять процессом выполнения и обеспечивать гибкость.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔 В чем разница между семафором и mutex?

Это два механизма синхронизации, используемые для управления доступом к общим ресурсам в многопоточном программировании. Хотя они часто используются для схожих целей, между ними есть важные различия.

🚩Мьютекс

🟠Взаимоисключение
Только один поток может владеть мьютексом в данный момент времени.
🟠Владелец
Поток, который захватил мьютекс, становится его владельцем и может его освободить.
🟠Блокировка на уровне ядра
Мьютексы обычно реализуются на уровне ядра операционной системы, что делает их более тяжелыми в плане ресурсов.
🟠Использование
Обычно используется для синхронизации доступа к критическим секциям кода.

public class Example
{
private static Mutex mutex = new Mutex();

public void UseResource()
{
mutex.WaitOne(); // Захват мьютекса
try
{
// Критическая секция
}
finally
{
mutex.ReleaseMutex(); // Освобождение мьютекса
}
}
}


🚩Семафор (Semaphore)

🟠Счетчик
Семафор имеет счетчик, который отслеживает количество разрешений. Потоки уменьшают счетчик при входе и увеличивают при выходе.

🟠Многократный доступ
В отличие от мьютекса, семафор позволяет нескольким потокам одновременно получать доступ к ресурсу, если счетчик больше нуля.

🟠Использование
Используется для управления доступом к ограниченным ресурсам, таким как пул соединений, доступ к базе данных и т. д.

public class Example
{
private static Semaphore semaphore = new Semaphore(3, 3); // Максимум 3 потока

public void UseResource()
{
semaphore.WaitOne(); // Захват семафора
try
{
// Критическая секция
}
finally
{
semaphore.Release(); // Освобождение семафора
}
}
}


🚩Ключевые различия:

🟠Владелец
Мьютекс: Может быть освобожден только потоком, который его захватил.
Семафор: Может быть освобожден любым потоком.

🟠Количество потоков
Мьютекс: Разрешает доступ только одному потоку.
Семафор: Разрешает доступ нескольким потокам, количество которых ограничено счетчиком.

🟠Использование
Мьютекс: Используется для защиты критических секций, где необходим доступ только одного потока.
Семафор: Используется для управления доступом к ресурсам, которые могут быть использованы одновременно несколькими потоками, но в ограниченном количестве.

🟠Реализация
Мьютекс: Обычно реализуется на уровне ядра операционной системы, что делает его более тяжелым.
Семафор: Может быть реализован как на уровне ядра, так и на уровне пользовательского кода.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14
🤔 Что такое абстракция?

Абстракция — это принцип ООП, который выделяет только важные характеристики объекта, скрывая сложные детали его реализации. Это помогает упростить взаимодействие с объектами и сконцентрироваться на их использовании, а не на внутренней структуре.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🤯2🔥1
🤔 Как middleware возвращает ответ?

В веб-приложениях, например, в ASP.NET Core, обрабатывает HTTP-запросы и формирует HTTP-ответы. Каждое middleware-компонент выполняет свою работу и передает управление следующему компоненту в конвейере или завершает обработку и формирует ответ.

🚩Основные моменты работы middleware

🟠Обработка запроса
Middleware получает запрос и может его обработать частично или полностью.
🟠Вызов следующего middleware
Если middleware не формирует окончательный ответ, оно вызывает следующий компонент в конвейере.
🟠Формирование ответа
Middleware может завершить обработку запроса, сформировав ответ, или пропустить управление следующему компоненту.

🚩Пример работы

Простое middleware
public class SimpleMiddleware
{
private readonly RequestDelegate _next;

public SimpleMiddleware(RequestDelegate next)
{
_next = next;
}

public async Task InvokeAsync(HttpContext context)
{
// Обработка запроса до следующего middleware
Console.WriteLine("Handling request.");

// Передача управления следующему middleware в конвейере
await _next(context);

// Обработка ответа после следующего middleware
Console.WriteLine("Handling response.");
}
}


Регистрация middleware в конвейере
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMiddleware<SimpleMiddleware>();
app.Run(async context =>
{
await context.Response.WriteAsync("Hello, World!");
});
}


🚩Возвращение ответа

🟠В самом middleware
Middleware может завершить обработку запроса и сразу вернуть ответ. Например, проверка аутентификации может вернуть 401 Unauthorized.
public class AuthMiddleware
{
private readonly RequestDelegate _next;

public AuthMiddleware(RequestDelegate next)
{
_next = next;
}

public async Task InvokeAsync(HttpContext context)
{
if (!context.User.Identity.IsAuthenticated)
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
await context.Response.WriteAsync("Unauthorized");
return; // Завершаем обработку, не вызывая _next
}

await _next(context);
}
}


🟠Через вызов следующего middleware
Если middleware вызывает следующий компонент в конвейере, то окончательный ответ может быть сформирован этим компонентом или одним из последующих.
public class LoggingMiddleware
{
private readonly RequestDelegate _next;

public LoggingMiddleware(RequestDelegate next)
{
_next = next;
}

public async Task InvokeAsync(HttpContext context)
{
// Логирование до обработки запроса
Console.WriteLine("Request incoming");

await _next(context);

// Логирование после обработки запроса
Console.WriteLine("Response outgoing");
}
}


🚩Ключевые моменты

🟠Последовательность
Middleware компоненты вызываются последовательно, в том порядке, в котором они зарегистрированы в Configure.
🟠Передача управления
Каждый middleware может передать управление следующему компоненту или завершить обработку, вернув ответ.
🟠Обработка ответа
После вызова следующего middleware текущий компонент может выполнять дополнительные действия с ответом (например, логирование).

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🤔 Что такое join в SQL?

JOIN — это операция в SQL, которая объединяет строки из двух или более таблиц на основе связующего условия. Существуют разные типы JOIN, такие как INNER JOIN (только совпадающие строки), LEFT JOIN (все строки из левой таблицы) и другие, обеспечивающие гибкость работы с данными.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍81🔥1
🤔 Что такое медиатор?

Это паттерн проектирования поведенческих шаблонов, который позволяет уменьшить связанность между объектами, обеспечивая взаимодействие через центральный объект-посредник. Медиатор упрощает коммуникацию между компонентами системы, делая ее более модульной и легкой для сопровождения.

🚩Примеры использования

1⃣Определение интерфейса медиатора
public interface IMediator
{
void Notify(object sender, string ev);
}


2⃣Реализация медиатора
public class DialogMediator : IMediator
{
private Button _button;
private TextBox _textBox;

public DialogMediator(Button button, TextBox textBox)
{
_button = button;
_button.SetMediator(this);
_textBox = textBox;
_textBox.SetMediator(this);
}

public void Notify(object sender, string ev)
{
if (ev == "ButtonClick")
{
_textBox.Clear();
}
else if (ev == "TextBoxEnter")
{
_button.SetEnabled(true);
}
}
}


3⃣Компоненты, взаимодействующие через медиатора
public class Button
{
private IMediator _mediator;

public void SetMediator(IMediator mediator)
{
_mediator = mediator;
}

public void Click()
{
Console.WriteLine("Button clicked");
_mediator.Notify(this, "ButtonClick");
}

public void SetEnabled(bool enabled)
{
Console.WriteLine($"Button is {(enabled ? "enabled" : "disabled")}");
}
}

public class TextBox
{
private IMediator _mediator;

public void SetMediator(IMediator mediator)
{
_mediator = mediator;
}

public void EnterText()
{
Console.WriteLine("Text entered");
_mediator.Notify(this, "TextBoxEnter");
}

public void Clear()
{
Console.WriteLine("TextBox cleared");
}
}


4⃣Использование медиатора в приложении
var button = new Button();
var textBox = new TextBox();
var mediator = new DialogMediator(button, textBox);

textBox.EnterText(); // Ввод текста активирует кнопку
button.Click(); // Нажатие кнопки очищает текстовое поле


🚩Плюсы и минусы

Снижение связанности
Компоненты не взаимодействуют напрямую, а используют медиатор.
Упрощение поддержки
Вся логика взаимодействия сосредоточена в одном месте.
Повышение модульности
Легко добавлять новые компоненты или изменять существующие.
Усложнение медиатора
Медиатор может стать сложным, если в него добавляется много логики.
Единая точка отказа
Если медиатор выходит из строя, это может повлиять на всю систему.

Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31