Основы объектно-ориентированного программирования, а также шаблоны программирования в C# с примерами их реализации, тестирование, объянение принципов и решение задач LetCode
Тип | Определение | Ключевые моменты |
---|---|---|
class | 🔎 Ссылка на объект, который может содержать поля, методы, свойства, события. | - Ссылка хранится в куче. - Поддерживает наследование и полиморфизм. - Может иметь конструкторы и деструкторы. |
abstract class | 🔎 Класс, который не может быть инстанцирован напрямую и может содержать абстрактные методы. | - Используется как базовый класс. - Может содержать как абстрактные, так и обычные методы. - Подклассы должны реализовать абстрактные методы. |
struct | 🔎 Значимый тип, который хранится на стеке и обычно используется для небольших объектов. | - Не поддерживает наследование от других struct. - Может реализовывать интерфейсы. - Используется для легковесных объектов. |
interface | 🔎 Контракт, определяющий набор методов, свойств и событий, которые должен реализовать класс или struct. | - Не содержит реализации (кроме default методов в C# 8+). - Позволяет реализовать полиморфизм. - Поддерживает множественную реализацию. |
record | 🔎 Ссылка или значимый тип с неизменяемыми свойствами и встроенной поддержкой сравнения по значению. | - Идеален для DTO и immutable объектов. - Поддерживает паттерн deconstruction. - Можно использовать с record class и record struct . |
Принцип | Определение | Ключевые моменты / Примеры |
---|---|---|
💢 Encapsulation (Инкапсуляция) | 🔎 Сокрытие внутреннего состояния объекта и предоставление доступа через контролируемые методы (getter/setter). | - Защищает данные от некорректного изменения. - Примеры: private fields + public методы. - Позволяет менять реализацию, не ломая API. |
💢 Abstraction (Абстракция) | 🔎 Выделение существенных характеристик объекта, скрывая детали реализации. | - Интерфейсы, абстрактные классы. - Клиент работает только с абстракцией, не зная конкретной реализации. |
💢 Inheritance (Наследование) | 🔎 Механизм создания нового класса на основе существующего, унаследовав его свойства и методы. | - Позволяет повторно использовать код. - Обеспечивает иерархию типов. - Важно не нарушать Liskov Substitution Principle. |
💢 Polymorphism (Полиморфизм) | 🔎 Возможность объектов разных классов использовать один и тот же интерфейс, реагируя на одинаковые методы по-разному. | - Compile-time (overloading), runtime (overriding). - Позволяет писать гибкий и расширяемый код. - Пример: метод Draw() у Circle и Rectangle . |
💢 Composition over Inheritance (Композиция вместо наследования) | 🔎 Предпочтение включения объектов в качестве полей, а не наследования, для повторного использования функционала. | - Улучшает гибкость. - Позволяет менять поведение во время выполнения. - Часто используется с паттернами (Strategy, Decorator). |
💢 SOLID (обобщение) | 🔎 Пять принципов, обеспечивающих устойчивую архитектуру: SRP, OCP, LSP, ISP, DIP. | - SRP – один класс = одна ответственность. - OCP – открыты для расширения, закрыты для изменения. - LSP – наследники заменяют базовый класс без слома. - ISP – интерфейсы узкоспециализированные. - DIP – зависимость на абстракциях, а не на деталях. |
💢 DRY (Don’t Repeat Yourself - Не повторяйся) | 🔎 Избегать дублирования кода, данных или логики. | - Любой элемент системы должен иметь единственное, недвусмысленное представление. - Дублирование ведёт к багам и трудной поддержке. - Используются функции, классы, наследование, утилитарные методы. |
💢 KISS (Keep It Simple, Stupid - Будь проще, глупый) | 🔎 Старайтесь делать решения простыми и понятными. | - Сложность усложняет поддержку и тестирование. - Минимизировать лишние абстракции. - Простые решения легче рефакторить и расширять. |
💢 YAGNI (You Aren’t Gonna Need It - Тебе это не понадобится) | 🔎 Не добавляй функциональность, пока она реально не нужна. | - Предотвращает перегрузку кода. - Избегает ненужных абстракций. - Часто сочетается с KISS. |
💢 LoD (Law of Demeter - Принцип минимальной связи) | 🔎 Объект должен взаимодействовать только с непосредственными «друзьями», а не с объектами объектов. | - Сокращает связанность модулей. - Пример: a.b.c() → лучше a.c() через делегирование.- Улучшает поддерживаемость и тестируемость. |
💢 POLA (Principle of Least Astonishment – Принцип минимального удивления) | 🔎 Поведение системы должно быть предсказуемым и логичным для разработчиков и пользователей. | - API должен работать так, как ожидает пользователь. - Нестандартные названия методов → нарушение POLA. - Собес: «Почему важно?» → уменьшает баги и кривой код. |
💢 TDA (Tell, Don’t Ask - Скажи, а не спрашивай) | 🔎 Говорите объекту, что делать, а не вытаскивайте его состояние и решайте что с ним делать снаружи. | - account.Deposit(100) лучше, чем balance = account.GetBalance(); balance += 100; - Уменьшает нарушаемость инкапсуляции. |
💢 SoC | 🔎 Каждый модуль / класс должен решать только одну задачу. | - Архитектура MVC / MVVM. - Меньше багов, легче рефакторить. - Собес: «Как проверяешь соблюдение?» → через тесты и код-ревью. |
💢 FF/FE (Fail Fast / Fail Early - Быстрый / Ранний провал) | 🔎 Система должна обнаруживать ошибки как можно раньше. | - Проверки аргументов (ArgumentNullException ).- Собес: «Зачем?» → уменьшает последствия ошибок и упрощает отладку. |
💢 CQS (Command Query Separation - Разделение команд и запросов) | 🔎 Команда и запрос разделены. | - Метод либо изменяет состояние (command), либо возвращает данные (query), но не одновременно. |
Название | Краткое описание |
---|---|
Single responsibility 💢 Принцип единственной ответственности |
🔎 Каждый модуль или класс должен иметь единую ответственность и выполнять её полностью. Через делегирование достигается чистота ответственности. SRP работает на уровне причин изменения, а не просто функций. |
Open-closed 💢 Принцип открытости/закрытости |
🔎 Программные сущности должны быть открыты для расширения, но закрыты для изменения: новые функциональные возможности добавляются через расширение, не изменяя существующий проверенный код. Применяется через абстракции, интерфейсы, наследование, паттерны проектирования. |
Liskov substitution 💢 Принцип подстановки Барбары Лисков |
🔎 Объекты наследника должны полностью заменять объекты базового класса, не нарушая ожидаемое поведение программы, включая предусловия, постусловия и инварианты. |
Interface Segregation 💢 Принцип разделения интерфейса |
🔎 Интерфейсы должны быть узкоспециализированными, а клиенты не должны зависеть от методов, которые они не используют. |
Dependency inversion 💢 Принцип инверсии зависисмостей |
🔎 Высокоуровневые модули не должны зависеть от модулей низкого уровня; оба должны зависеть от абстракций. Абстракции не должны зависеть от деталей, детали должны зависеть от абстракций. |
Принцип | Уровень применения | Основная идея |
---|---|---|
SRP | Класс / модуль | Один класс = одна причина для изменения |
SoC | Архитектура / слой / система | Разделяем ответственность на независимые компоненты и слои |
Паттерн | Краткое определение |
---|---|
💢 ChainOfResponsibility - Цепочка обязанностей | 🔎 Избегает связывание отправителя запроса с его получателем, давая возможность обработать запрос более чем одному объекту. |
💢 Command - Команда | 🔎 Инкапсулирует запрос в виде объекта, позволяя передавать их клиентам в качестве параметров, ставить в очередь, логировать, а также поддерживать отмену операций. |
💢 Interpreter - Интерпретатор | 🔎 Получая формальный язык, определяет представление его грамматики и интерпретатор, использующий это представление для обработки выражений языка. |
💢 Iterator - Итератор | 🔎 Предоставляет способ последовательного доступа к множеству, независимо от его внутреннего устройства. |
💢 Mediator - Посредник | 🔎 Определяет объект, инкапсулирующий способ взаимодействия объектов. Обеспечивает слабую связь, избавляя их от необходимости ссылаться друг на друга, и даёт возможность независимо изменять их взаимодействие. |
💢 Memento - Хранитель | 🔎 Не нарушая инкапсуляцию, определяет и сохраняет внутреннее состояние объекта и позволяет позже восстановить объект в этом состоянии. |
💢 Observer - Наблюдатель | 🔎 Определяет зависимость один ко многим между объектами так, что когда один меняет своё состояние, все зависимые объекты оповещаются и обновляются автоматически. |
💢 State - Состояние | 🔎 Позволяет объекту изменять своё поведение в зависимости от внутреннего состояния. |
💢 Strategy - Стратегия | 🔎 Определяет группу алгоритмов, инкапсулирует их и делает взаимозаменяемыми. Позволяет изменять алгоритм независимо от клиентов, его использующих. |
💢 TemplateMethod - Шаблонный метод | 🔎 Определяет алгоритм, некоторые этапы которого делегируются подклассам. Позволяет подклассам переопределить эти этапы, не меняя структуру алгоритма. |
💢 Visitor - Посетитель | 🔎 Представляет собой операцию, которая будет выполнена над объектами группы классов. Даёт возможность определить новую операцию без изменения кода классов, над которыми эта операция производится. |
Паттерн | Краткое определение |
---|---|
💢 AbstractFactory - Абстрактная фабрика | 🔎 Предоставляет интерфейс для создания групп связанных или зависимых объектов, не указывая их конкретный класс. |
💢 Builder - Строитель | 🔎 Разделяет создание сложного объекта и его инициализацию так, что одинаковый процесс построения может создавать объекты с разным состоянием. |
💢 FactoryMethod - Фабричный метод | 🔎 Определяет интерфейс для создания объекта, но позволяет подклассам решать, какой класс создавать. Позволяет делегировать создание класса объектам класса. |
💢 FluentBuilder - Гибкий (плавный, текучий) строитель | 🔎 Позволяет упростить процесс создания сложных объектов с помощью методов-цепочек, которые наделяют объект определенным качеством. |
💢 Prototype - Прототип | 🔎 Определяет несколько видов объектов, чтобы при создании использовать объект-прототип и создавать новые объекты, копируя прототип (техника клонирования объектов). |
💢 Singleton - Одиночка | 🔎 Гарантирует, что класс имеет только один экземпляр, и представляет глобальную точку доступа к нему. |
Паттерн | Краткое определение |
---|---|
💢 Adapter - Адаптер | 🔎 Конвертирует интерфейс класса в другой интерфейс, ожидаемый клиентом. Позволяет классам с разными интерфейсами работать вместе. |
💢 Bridge - Мост | 🔎 Разделяет абстракцию и реализацию так, чтобы они могли изменяться независимо друг от друга. |
💢 Composite - Компоновщик | 🔎 Компонует объекты в древовидную структуру по принципу “часть-целое”, представляя их в виде иерархии. Позволяет клиенту одинаково обращаться как к отдельному, так и к целому поддереву. |
💢 Decorator - Декоратор | 🔎 Динамически предоставляет объекту дополнительные возможности. Гибкая альтернатива наследованию для расширения функциональности. |
💢 Facade - Фасад | 🔎 Предоставляет единый интерфейс к группе интерфейсов подсистемы. Делает систему проще для использования. |
💢 Flyweight - Приспособленец | 🔎 Благодаря совместному использованию поддерживает эффективную работу с большим количеством объектов (оптимизация памяти). |
💢 Proxy - Заместитель | 🔎 Предоставляет объект-заместитель другого объекта для контроля доступа к нему. |
Коллекция | Назначение / Описание | Особенности |
---|---|---|
💢 Dictionary<TKey, TValue> | 🔎 Хранит пары ключ-значение, обеспечивает быстрый доступ по ключу. | - Ключи уникальны. - Быстрый поиск, вставка и удаление (обычно O(1)). - Нет гарантии порядка элементов. |
💢 SortedDictionary<TKey, TValue> | 🔎 Хранит пары ключ-значение, упорядоченные по ключу. | - Ключи уникальны. - Элементы автоматически сортируются. - Операции вставки и поиска медленнее, чем в Dictionary. |
💢 ConcurrentDictionary<TKey, TValue> | 🔎 Потокобезопасная коллекция для многопоточного доступа. | - Безопасна для параллельного чтения и записи. - Методы: TryAdd, TryRemove, GetOrAdd. - Используется в многопоточных приложениях. |
💢 ReadOnlyDictionary<TKey, TValue> | 🔎 Обёртка над Dictionary, предоставляющая только чтение. | - Изменять коллекцию нельзя. - Используется для безопасной передачи наружу. |
💢 ListDictionary | 🔎 Маленький словарь (до ~10 элементов), реализованный как связанный список. | - Оптимален для небольшого количества элементов. - Последовательный поиск (O(n)). - Используется в старых .NET приложениях. |
💢 HybridDictionary | 🔎 Комбинация ListDictionary и Hashtable. | - Маленькие коллекции хранятся как ListDictionary. - При росте коллекции автоматически преобразуется в Hashtable. - Оптимизация под маленькие и средние словари. |
Термин / Инструмент | Описание / Назначение |
---|---|
💢 Unit-тест | Автоматический тест для отдельного модуля или метода, проверяет его корректность независимо от других частей системы. |
💢 Arrange-Act-Assert (AAA) | Структура теста: - Arrange – подготовка данных и состояния. - Act – выполнение тестируемого метода. - Assert – проверка результата. |
💢 Mock / Stub | Заглушки для зависимостей: - Mock – проверяет, что методы вызваны. - Stub – возвращает фиксированные данные. |
💢 Frameworks | Инструменты для тестирования: - NUnit, xUnit, MSTest – популярные фреймворки для C#. |
💢 Плюсы Unit-тестов | - Быстрая проверка кода. - Легче отлавливать баги. - Позволяет безопасно рефакторить. |
💢 Минусы / ограничения | - Не тестируют интеграцию с другими модулями. - Требуют поддержки и актуальности тестов. |
💢 TDD (Test-Driven Development) | Подход разработки через тесты: 1. Пишем тест. 2. Реализуем функционал. 3. Рефакторим код. |
✨Dvurechensky✨