Это технология, обеспечивающая двустороннюю связь между клиентом и сервером через один TCP-соединение. В отличие от традиционного HTTP, который работает по принципу запрос-ответ, WebSockets позволяют передавать данные в обоих направлениях в режиме реального времени, что делает их идеальными для приложений, требующих мгновенного обмена данными.
Клиент и сервер могут отправлять данные друг другу независимо, без необходимости инициировать новый запрос.
После установления WebSocket-соединение остается открытым, что позволяет передавать данные с минимальной задержкой.
Меньшие накладные расходы по сравнению с HTTP, так как заголовки передаются только при установлении соединения, а не для каждого сообщения.
Поддержка большого количества одновременных соединений, что полезно для чатов, игр и других приложений с интенсивным обменом данными.
Клиент инициирует соединение с сервером через HTTP-запрос с заголовком
Upgrade, указывая, что он хочет перейти на WebSocket-протокол.Сервер отвечает согласием на переход на WebSocket-протокол, и соединение устанавливается.
После установления соединения данные могут передаваться в обоих направлениях до тех пор, пока одно из сторон не закроет соединение.
Сервер на Python с использованием библиотеки
websocketsimport asyncio
import websockets
async def handler(websocket, path):
async for message in websocket:
print(f"Received message: {message}")
await websocket.send(f"Echo: {message}")
start_server = websockets.serve(handler, "localhost", 8765)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
Клиент на JavaScript
const socket = new WebSocket('ws://localhost:8765');
socket.onopen = function(event) {
console.log('WebSocket is open now.');
socket.send('Hello, Server!');
};
socket.onmessage = function(event) {
console.log(`Message from server: ${event.data}`);
};
socket.onclose = function(event) {
console.log('WebSocket is closed now.');
};
socket.onerror = function(error) {
console.log(`WebSocket error: ${error}`);
};Подходит для приложений, где важна минимальная задержка, таких как чаты, игровые приложения и финансовые торговые платформы.
Меньшее количество данных передается по сети по сравнению с традиционными HTTP-запросами.
Простота в использовании и поддержка большинством современных браузеров.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊6👍2🔥1🤔1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥1
Semaphore – классический семафор, использующий ядро операционной системы для синхронизации потоков. SemaphoreSlim – более лёгкая и быстрая версия, работающая в основном на уровне управляемого кода без вызовов ядра ОС. Используйте
Semaphore, если: Вам нужно разделение ресурсов между разными процессами.
Вы работаете с нативным кодом или сторонними API, использующими семафоры ОС.
Используйте
SemaphoreSlim, если: Вам нужна быстрая блокировка между потоками в одном процессе.
Вы хотите использовать асинхронный код (
async/await). Вам важна производительность.
using System;
using System.Threading;
class Program
{
static Semaphore semaphore = new Semaphore(2, 2); // Макс. 2 потока могут войти одновременно
static void Main()
{
for (int i = 1; i <= 5; i++)
{
new Thread(DoWork).Start(i);
}
}
static void DoWork(object id)
{
Console.WriteLine($"Поток {id} ждёт семафор...");
semaphore.WaitOne(); // Захватываем семафор
Console.WriteLine($"Поток {id} выполняет работу...");
Thread.Sleep(2000); // Симуляция работы
Console.WriteLine($"Поток {id} освобождает семафор");
semaphore.Release(); // Освобождаем семафор
}
}
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(2); // 2 потока одновременно
static async Task Main()
{
Task[] tasks = new Task[5];
for (int i = 0; i < 5; i++)
{
tasks[i] = DoWork(i);
}
await Task.WhenAll(tasks);
}
static async Task DoWork(int id)
{
Console.WriteLine($"Задача {id} ждёт семафор...");
await semaphoreSlim.WaitAsync(); // Асинхронное ожидание
Console.WriteLine($"Задача {id} выполняет работу...");
await Task.Delay(2000); // Симуляция работы
Console.WriteLine($"Задача {id} освобождает семафор");
semaphoreSlim.Release(); // Освобождаем семафор
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
Forwarded from Софи и партнеры
🎉Разыгрываем пожизненный доступ к AI-ассистенту для поиска работы для 3 подписчиков
До запуска Софи остается меньше месяца, поэтому мы решили порадовать вас и устроить конкурс, приуроченный к этому событию.
Кто такая Софи?
Это первый в России ассистент по поиску работы, который будет сам делать отклики, писать сопроводительные письма, поможет с резюме и подготовкой к собесу, а еще избавит тебя от отказов.
Мы работали над ней более полугода, и сейчас хотим подарить бесплатный пожизненный доступ для 3 наших подписчиков.
Мы посчитали, стоимость одной такой подписки ну хотя бы на 10 лет составляла бы 420.000 руб.
Условия конкурса простые:
1. Подписаться на 4 наших канала:
Софи и партнёры
Young & Junior - вакансии IT
Young Стажёр - стажировки ИТ
IT мероприятия для стажеров и студентов
2. Нажать кнопку "участвую" под этим постом.
15 июля, в 19:00, мы в прямом эфире проведем запуск Софи, а в 20:00 опубликуем результаты конкурса в канале Софи и Партнёры.
Каждый победитель получит бесплатный доступ к Софи навсегда.
Всем удачи и до встречи в прямом эфире🚀
До запуска Софи остается меньше месяца, поэтому мы решили порадовать вас и устроить конкурс, приуроченный к этому событию.
Кто такая Софи?
Это первый в России ассистент по поиску работы, который будет сам делать отклики, писать сопроводительные письма, поможет с резюме и подготовкой к собесу, а еще избавит тебя от отказов.
Мы работали над ней более полугода, и сейчас хотим подарить бесплатный пожизненный доступ для 3 наших подписчиков.
Мы посчитали, стоимость одной такой подписки ну хотя бы на 10 лет составляла бы 420.000 руб.
Условия конкурса простые:
1. Подписаться на 4 наших канала:
Софи и партнёры
Young & Junior - вакансии IT
Young Стажёр - стажировки ИТ
IT мероприятия для стажеров и студентов
2. Нажать кнопку "участвую" под этим постом.
15 июля, в 19:00, мы в прямом эфире проведем запуск Софи, а в 20:00 опубликуем результаты конкурса в канале Софи и Партнёры.
Каждый победитель получит бесплатный доступ к Софи навсегда.
Всем удачи и до встречи в прямом эфире🚀
- private — доступен только внутри текущего класса.
- protected — доступен внутри текущего класса и его наследников.
private обеспечивает максимальную инкапсуляцию, а protected позволяет наследникам переопределять поведение или использовать базовые методы.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
IEnumerable — это интерфейс в базовой библиотеке классов .NET Framework, который определяет один метод:
GetEnumerator(). Этот метод возвращает объект IEnumerator, который позволяет перебирать элементы коллекции (например, массива или списка) один за другим.Используется для создания универсального метода перебора данных, не зависящего от типа коллекции. Это означает, что любой тип данных, который реализует
IEnumerable, можно перебирать с помощью цикла foreach в C#. Это упрощает работу с различными структурами данных, предоставляя единый механизм для итерации элементов.Когда вы реализуете интерфейс
IEnumerable в своём классе, вы обязуете этот класс предоставлять метод GetEnumerator(), который возвращает IEnumerator. IEnumerator, в свою очередь, имеет методы для перехода к следующему элементу (MoveNext) и для получения текущего элемента (Current), а также метод Reset(), который возвращает перечислитель в начальное состояние.using System;
using System.Collections;
public class DaysOfWeek : IEnumerable
{
private string[] days = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
public IEnumerator GetEnumerator()
{
for (int index = 0; index < days.Length; index++)
{
// Yield each day of the week.
yield return days[index];
}
}
}
public class Program
{
public static void Main()
{
DaysOfWeek daysOfWeek = new DaysOfWeek();
foreach (string day in daysOfWeek)
{
Console.WriteLine(day);
}
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5💊1
Смысл — в оптимизации работы сборщика мусора (GC):
- Сборка мусора чаще всего затрагивает именно Generation 0, потому что большинство объектов живут недолго.
- Если объект "пережил" сборку — он перемещается в следующее поколение (Gen 1, затем Gen 2).
- Это уменьшает нагрузку на сборщик, ведь старые объекты проверяются реже.
Таким образом, жизнь в Gen 0 коротка, если объект быстро умирает. Но если нужен — он "повзрослеет".
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊4
Да, порядок
catch имеет значение! Исключения проверяются сверху вниз, и первый подходящий
catch будет выполнен. 1. Исключение проверяется по порядку
catch-блоков. 2. Если
catch подходит → он выполняется, остальные игнорируются. 3. Специфичные исключения (
DivideByZeroException) нужно ставить выше общих (Exception). Так делать нельзя!
try
{
int x = 5 / 0; // Ошибка
}
catch (Exception ex) // Ловит все исключения
{
Console.WriteLine("Общая ошибка");
}
catch (DivideByZeroException ex) // Никогда не выполнится!
{
Console.WriteLine("Деление на ноль!");
}
Правильный порядок
catchtry
{
int x = 5 / 0;
}
catch (DivideByZeroException ex) // Специфичный `catch` первым
{
Console.WriteLine("Ошибка: деление на ноль!");
}
catch (Exception ex) // Общий `catch` внизу
{
Console.WriteLine("Произошла ошибка!");
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
Нет, не всегда.
Полная нормализация может усложнить архитектуру и замедлить чтение данных из-за большого числа JOIN'ов. Поэтому часто применяют компромисс между нормализацией и денормализацией, особенно в high-load системах.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
В трехслойной архитектуре (трехуровневая архитектура), также известной как многоуровневая архитектура, приложения разделяются на три логических слоя:
Отвечает за взаимодействие с пользователем. Веб-интерфейсы, мобильные приложения, десктопные приложения. Примеры: HTML/CSS/JavaScript для веб-приложений, UI-компоненты в мобильных и десктопных приложениях.
Содержит бизнес-логику и правила приложения. Обрабатывает данные, выполняет вычисления, применяет бизнес-правила. Примеры: классы и методы, реализующие бизнес-логику, сервисы, обработчики данных.
Отвечает за взаимодействие с источниками данных. Операции с базами данных, файловыми системами, внешними сервисами. Примеры: репозитории, Data Access Objects (DAO), API-клиенты для доступа к внешним системам.
REST — это архитектурный стиль для разработки веб-сервисов. RESTful сервисы используют стандартные HTTP методы (GET, POST, PUT, DELETE и т.д.) для работы с ресурсами.
С точки зрения трехслойной архитектуры:
Презентационный слой:
Вызовы REST API могут происходить с клиентской стороны (например, AJAX запросы из веб-интерфейса) или через клиентские приложения.
Пример: фронтенд веб-приложения, который взаимодействует с REST API.
Логический слой:
REST API реализует бизнес-логику и выступает посредником между презентационным слоем и слоем данных.
Пример: контроллеры и сервисы, обрабатывающие REST запросы и выполняющие соответствующую бизнес-логику.
Слой данных:
REST API может взаимодействовать с базой данных или другими источниками данных для получения и сохранения информации.
Пример: методы в API, которые выполняют запросы к базе данных через репозитории или DAO.
SWAP — это гипотетический или менее распространенный термин, часто интерпретируемый как упрощенный API для веб-приложений.
Презентационный слой
Клиентские приложения или пользовательские интерфейсы могут вызывать методы SWAP для получения или отправки данных.Пример: веб-страницы или мобильные приложения, обращающиеся к SWAP для выполнения операций.
Логический слой:
SWAP обрабатывает бизнес-логику аналогично REST API, предоставляя упрощенные конечные точки для взаимодействия с данными.
Пример: сервисы, которые реализуют простые операции (CRUD) без сложной бизнес-логики.
Слой данных:
SWAP взаимодействует с базой данных или другими источниками данных для выполнения операций чтения/записи.
Пример: методы SWAP, которые обращаются к базе данных через абстрактные уровни доступа к данным.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
- HTTP/HTTPS — основной протокол для REST API, веба.
- WebSocket — для двустороннего постоянного соединения.
- gRPC — высокопроизводительный бинарный протокол на базе HTTP/2.
- SOAP — устаревший, но формализованный протокол обмена XML.
- MQTT, AMQP — легкие брокерные протоколы (например, для IoT).
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5
Это делегат, представляющий метод, который принимает один или несколько аргументов и возвращает логическое значение (
true или false). Предикаты часто используются для фильтрации коллекций, поиска элементов и других операций, связанных с условными проверками.В C# предикат представлен делегатом
Predicate<T>, который принимает один аргумент типа T и возвращает bool.Предикаты обычно используются в методах стандартных коллекций, таких как
List<T>, для поиска, удаления и фильтрации элементов.Определение предиката
public static bool IsEven(int number)
{
return number % 2 == 0;
}
Использование предиката с методом коллекции
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
// Использование предиката для поиска первого четного числа
int firstEven = numbers.Find(IsEven);
Console.WriteLine("First even number: " + firstEven);
// Использование предиката для удаления всех четных чисел
numbers.RemoveAll(IsEven);
Console.WriteLine("Numbers after removing evens: " + string.Join(", ", numbers));
}
public static bool IsEven(int number)
{
return number % 2 == 0;
}
}
Лямбда-выражения часто используются для определения предикатов непосредственно в месте вызова метода. Это делает код более компактным и удобочитаемым.
Пример использования лямбда-выражений
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6 };
// Использование лямбда-выражения для поиска первого четного числа
int firstEven = numbers.Find(n => n % 2 == 0);
Console.WriteLine("First even number: " + firstEven);
// Использование лямбда-выражения для удаления всех четных чисел
numbers.RemoveAll(n => n % 2 == 0);
Console.WriteLine("Numbers after removing evens: " + string.Join(", ", numbers));
}
}
Предикаты используются для определения условий фильтрации элементов в коллекциях.
List<int> evenNumbers = numbers.FindAll(IsEven);
Предикаты помогают находить элементы, соответствующие определенному условию.
int firstEven = numbers.Find(IsEven);
Предикаты используются для удаления элементов, соответствующих определенному условию.
numbers.RemoveAll(IsEven);
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3💊1
- Статический класс (static):
- Нельзя создать экземпляр (new).
- Все методы и поля внутри него тоже должны быть static.
- Используется как утилитный контейнер.
- Нестатический класс:
- Можно создавать объекты.
- Может содержать как обычные, так и статические члены.
- Поддерживает наследование, интерфейсы, абстракции и т.д.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3
.NET Standard — это спецификация API, которая определяет набор базовых библиотек, доступных во всех реализациях .NET (например, .NET Framework, .NET Core, Xamarin, Unity и других). Она была создана для обеспечения совместимости между разными платформами .NET.
До появления .NET Standard существовало несколько отдельных реализаций .NET:
.NET Framework (для Windows-приложений)
.NET Core (кроссплатформенная версия .NET)
Mono/Xamarin (для мобильных и игровых приложений)
Каждая из них имела свои особенности и набор доступных API. Из-за этого разработчики, создавая библиотеку, сталкивались с проблемой совместимости: приходилось писать несколько версий кода под разные платформы или использовать Portable Class Library (PCL), которая имела ограниченный функционал.
.NET Standard решил эту проблему, введя единый набор API, который обязаны поддерживать все реализации .NET.
.NET Standard представляет собой абстрактную спецификацию API, которая реализуется разными версиями .NET. Например, .NET Standard 2.0 поддерживается в .NET Framework 4.6.1, .NET Core 2.0 и выше. Если библиотека написана под .NET Standard 2.0, её можно использовать во всех этих средах.
Существуют разные версии .NET Standard, каждая из которых включает больше API, чем предыдущая. Чем выше версия, тем больше возможностей, но и тем меньше совместимость с более старыми реализациями .NET.
Создаём Class Library с таргетом
.NET Standard 2.0:namespace MyLibrary
{
public class MathHelper
{
public static int Add(int a, int b)
{
return a + b;
}
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Да, можно. Обобщённые (generic) методы не требуют, чтобы сам класс был обобщённым.
Такие методы объявляются с использованием шаблонного параметра <T> непосредственно в сигнатуре метода.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Сборщик мусора (Garbage Collector, GC) в .NET автоматически управляет памятью, освобождая неиспользуемые объекты.
GC сам решает, когда запуститься, исходя из:
Заполнения памяти (Heap почти полный)
Недостатка ресурсов (мало RAM)
Давления на систему
class Program
{
static void Main()
{
for (int i = 0; i < 100000; i++)
{
var obj = new object(); // Создаётся много объектов
} // После выхода из цикла ненужные объекты освобождаются GC
}
}
Можно форсировать сборку мусора, но это редко рекомендуется**, так как GC сам лучше решает, когда запускаться.
GC.Collect(); // Принудительный запуск сборщика мусора
GC.WaitForPendingFinalizers(); // Дождаться завершения финализаторов
GC не сразу удаляет объекты с ресурсами (файлы, сокеты).
Такие объекты лучше очищать вручную через
Dispose() или using. using (StreamWriter writer = new StreamWriter("file.txt"))
{
writer.WriteLine("Привет, мир!");
} // `Dispose()` вызовется автоматическиСтавь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔1
SQL поддерживает несколько уровней изоляции транзакций, которые определяют, какие изменения видны между конкурентными транзакциями:
- Read Uncommitted – транзакции могут читать "грязные" (неподтвержденные) данные из других транзакций. Возможны аномалии.
- Read Committed – транзакция видит только подтвержденные изменения других транзакций. Исключает "грязные" чтения.
- Repeatable Read – гарантирует, что данные, прочитанные в одной транзакции, не изменятся до ее завершения. Возможны фантомные чтения.
- Serializable – самый строгий уровень, полностью исключает аномалии за счет блокировки записей или использования версионности.
- Snapshot (в SQL Server) – каждая транзакция работает со "снимком" данных, исключая конфликты без блокировок.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5
Это структура данных, используемая в системах управления базами данных (СУБД) для организации и ускорения доступа к данным. B-tree индекс является сбалансированным деревом, обеспечивающим эффективное выполнение операций поиска, вставки, удаления и диапазонного поиска. B-tree индекс используется большинством реляционных СУБД, таких как SQL Server, MySQL, PostgreSQL и Oracle.
B-tree индекс является сбалансированным деревом, где все листья находятся на одном уровне. Это обеспечивает равномерное время доступа к данным.
В узлах B-tree хранятся ключи, которые могут ссылаться на строки в таблице или на другие узлы дерева.
Ключи в каждом узле упорядочены, что позволяет эффективно выполнять бинарный поиск внутри узла.
B-tree индекс эффективно поддерживает диапазонные запросы (например, поиск всех записей с ключами между заданными значениями).
B-tree автоматически сбалансирован, что позволяет эффективно выполнять операции вставки, удаления и обновления.
CREATE TABLE Employees (
EmployeeID INT PRIMARY KEY,
FirstName VARCHAR(50),
LastName VARCHAR(50),
DepartmentID INT,
Salary DECIMAL(10, 2)
);
CREATE INDEX idx_lastname ON Employees(LastName);
Операция поиска в B-tree выполняется за логарифмическое время O(log n), где n — количество узлов.
SELECT * FROM Employees WHERE LastName = 'Smith';
Диапазонные запросы, такие как поиск всех сотрудников с фамилией от 'A' до 'M', выполняются эффективно.
SELECT * FROM Employees WHERE LastName BETWEEN 'A' AND 'M';
При вставке новой записи в таблицу с индексом B-tree, запись добавляется в соответствующее место, поддерживая балансировку дерева.
INSERT INTO Employees (EmployeeID, FirstName, LastName, DepartmentID, Salary)
VALUES (1, 'John', 'Doe', 10, 60000.00);
При удалении записи соответствующий ключ удаляется из B-tree, и дерево автоматически перестраивается, чтобы сохранить балансировку.
DELETE FROM Employees WHERE EmployeeID = 1;
Обеспечивает быстрый доступ к данным благодаря сбалансированной структуре дерева.
Поддерживает операции вставки, удаления и поиска с логарифмической сложностью.
Эффективно обрабатывает диапазонные запросы благодаря упорядоченной структуре.
Динамическая балансировка дерева обеспечивает равномерное время доступа и вставки/удаления.
Требует дополнительного пространства для хранения структуры дерева и ключей.
Вставка и удаление могут требовать перестроения узлов, что влечет за собой дополнительные вычислительные затраты.
При частых операциях вставки и удаления может возникнуть фрагментация, что может потребовать периодического обслуживания (например, реорганизации индекса).
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Да, асинхронный код можно вызвать синхронно, но это не рекомендуется. Использование .Result или .GetAwaiter().GetResult() позволяет получить результат синхронно, однако это может привести к блокировкам, дедлокам и снижению производительности, особенно в UI-приложениях или в серверных окружениях с синхронным контекстом.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from easyoffer
🎉 easyoffer 2.0 — релиз уже в этом месяце!
Вас ждут новые фичи, о которых мы ранее даже не упоминали. Они сделают путь к офферам ещё быстрее и эффективнее. Расскажу о них чуть позже 👀
В честь запуска мы готовим ограниченную акцию:
Первые 500 покупателей получат:
🚀 PRO тариф на 1 год с 50% скидкой
Что нужно сделать:
🔔 Подпишитесь на этот Telegram-канал, чтобы первыми узнать о старте релиза. Сообщение появится в нем раньше, чем где-либо еще — вы успеете попасть в число первых 500 и получить максимальную выгоду. 🎁 А еще только для подписчиков канала ценный бонус в подарок к PRO тарифу.
📅 Официальный запуск — уже совсем скоро.
Следите за новостями и не пропустите старт!
Вас ждут новые фичи, о которых мы ранее даже не упоминали. Они сделают путь к офферам ещё быстрее и эффективнее. Расскажу о них чуть позже 👀
В честь запуска мы готовим ограниченную акцию:
Первые 500 покупателей получат:
🚀 PRO тариф на 1 год с 50% скидкой
Что нужно сделать:
🔔 Подпишитесь на этот Telegram-канал, чтобы первыми узнать о старте релиза. Сообщение появится в нем раньше, чем где-либо еще — вы успеете попасть в число первых 500 и получить максимальную выгоду. 🎁 А еще только для подписчиков канала ценный бонус в подарок к PRO тарифу.
📅 Официальный запуск — уже совсем скоро.
Следите за новостями и не пропустите старт!
Паттерн "Строитель" (Builder) используется для пошагового создания сложных объектов. Он удобен, когда объект имеет много параметров и возможных конфигураций.
Допустим, у нас есть класс
Car, и мы хотим создавать машины с разными конфигурациями:public class Car
{
public string Engine { get; set; }
public int Wheels { get; set; }
public bool HasSunroof { get; set; }
public override string ToString()
{
return $"Car: Engine={Engine}, Wheels={Wheels}, Sunroof={HasSunroof}";
}
}
Создавать объект через конструкторы или инициализаторы становится неудобно, если у нас много параметров:
var car1 = new Car { Engine = "V8", Wheels = 4, HasSunroof = true };
var car2 = new Car { Engine = "V6", Wheels = 4, HasSunroof = false };Сделаем пошаговый процесс сборки объекта с помощью паттерна "Строитель".
Шаг 1: Создаём интерфейс строителя
public interface ICarBuilder
{
ICarBuilder SetEngine(string engine);
ICarBuilder SetWheels(int wheels);
ICarBuilder SetSunroof(bool hasSunroof);
Car Build();
}
Шаг 2: Реализуем конкретного строителя
public class CarBuilder : ICarBuilder
{
private Car _car = new Car(); // Временный объект
public ICarBuilder SetEngine(string engine)
{
_car.Engine = engine;
return this; // Возвращаем самого себя для цепочки вызовов
}
public ICarBuilder SetWheels(int wheels)
{
_car.Wheels = wheels;
return this;
}
public ICarBuilder SetSunroof(bool hasSunroof)
{
_car.HasSunroof = hasSunroof;
return this;
}
public Car Build()
{
return _car; // Возвращаем готовый объект
}
}
Шаг 3: Используем строителя
class Program
{
static void Main()
{
ICarBuilder builder = new CarBuilder();
Car sportsCar = builder
.SetEngine("V8")
.SetWheels(4)
.SetSunroof(true)
.Build();
Car economyCar = builder
.SetEngine("V4")
.SetWheels(4)
.SetSunroof(false)
.Build();
Console.WriteLine(sportsCar);
Console.WriteLine(economyCar);
}
}
Вывод в консоли
Car: Engine=V8, Wheels=4, Sunroof=True
Car: Engine=V4, Wheels=4, Sunroof=False
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM