В этом видео я объясню концепцию объектно-ориентированной парадигмы простым языком и на наглядных примерах. Обсуждаемые концепции не зависят от какого-либо конкретного языка программирования и будут полезны для JavaScript, Java, C++ и т.д. Все примеры будут показаны на машинописном языке, но понятны и разработчикам Java.
Процедурный подход - это традиционный способ программирования, при котором программа пишется поэтапно с использованием процедур или функций. Он фокусируется на выполнении ряда шагов для достижения результата. Однако по мере того, как программы становились больше и сложнее, стало понятно, что процедурный подход имеет ограничения с точки зрения управления сложностью и масштабируемостью.
Объектно-ориентированный подход Объектно-ориентированный подход воспринимается как грандиозное решение, способное решить все проблемы. Он включает в себя два фундаментальных понятия: "класс" и "объект". Класс представляет характеристики сущности, в то время как объект - это конкретный экземпляр со значимыми значениями для каждой характеристики.
Ключевые элементы ООП В ООП классы имеют свойства (такие как имя, возраст) и методы (например, ходьба или рисование). Примером является класс rectangle со свойствами ширины, высоты и методом вычисления его площади. У каждого класса может быть несколько объектов с разными значениями свойств. Надлежащая практика предписывает включать в каждый класс только необходимые свойства и методы.
Инкапсуляция Инкапсуляция - это концепция содержания свойств и методов внутри класса, позволяющая получить к ним доступ только изнутри класса. Она тесно пересекается с концепцией сокрытия данных или информации.
Модификаторы доступа Модификаторы доступа, такие как public и private, определяют, можно ли получить доступ к свойствам и методам снаружи или внутри класса. К частным свойствам нельзя получить прямой доступ извне класса, что обеспечивает безопасность данных.
Добытчики и установщики 'Getter' извлекает значения свойств, в то время как 'setter' устанавливает новые значения для частных свойств. Они обеспечивают контролируемый доступ к закрытым элементам, позволяя выполнять внешние манипуляции с помощью определенных методов.
Примеры сценариев Класс 'User' демонстрирует инкапсуляцию, используя средства получения/установки для имени пользователя, пароля и уникального идентификатора (aidishnik). Пример 'DatabaseConnection' показывает, как инкапсуляция ограничивает прямое изменение, но допускает контролируемое взаимодействие с помощью определенных общедоступных методов.
Наследование в объектно-ориентированном программировании Наследование является фундаментальной концепцией в объектно-ориентированном программировании. Оно позволяет классу наследовать свойства и методы от другого класса, расширяя функциональность производного класса.
Расширение классов дополнительными свойствами Классы могут быть расширены для добавления новых свойств при наследовании существующих. Это позволяет создавать уникальные иерархии классов с их собственными отличными атрибутами и методами.
Использование наследования для создания иерархий классов Используя наследование, становится возможным создавать целые иерархии классов, которые обладают своими собственными уникальными характеристиками и методами, унаследованными от родительских классов. Каждый производный класс наследует свойства и методы от своего родительского класса, что обеспечивает эффективное повторное использование кода.
Понимание полиморфизма Полиморфизм - это принцип, который позволяет фрагменту кода работать с различными типами данных. Он имеет два основных типа: параметрический полиморфизм и специальный полиморфизм.
Специальный полиморфизм Специальный полиморфизм предполагает перегрузку метода, когда метод работает с несколькими типами данных из-за различий в типах параметров. Это позволяет одному методу эффективно обрабатывать различные входные данные.
Параметрический полиморфизм Параметрический полиморфизм имеет дело с обработкой неограниченного количества объектов, унаследованных от родительского класса, путем переопределения методов в каждом подклассе. Этот подход гарантирует, что одна и та же функция может приветствовать разные экземпляры объектов на основе их конкретных классов.
Агрегация и состав В этой главе мы исследуем взаимодействие между классами посредством наследования. Мы обсуждаем агрегацию и композицию на примерах класса automobile с двигателем и колесами в качестве объектов, демонстрируя, как они не могут существовать отдельно от автомобиля в отношениях композиции. Кроме того, мы исследуем объект Christmas tree, который передается конструктору класса automobile извне, иллюстрируя его независимость в отношении агрегации.
Разница между агрегацией и составом Здесь мы подчеркиваем различие между агрегированием и композицией, создавая классы для автомобиля с двигателем и колесами в качестве объектов внутри его конструктора. Метод drive внутри каждого объекта демонстрирует поведение делегирования в обоих случаях. Затем мы вводим свойство freshener как часть класса car, но инициализируем его извне, чтобы продемонстрировать его независимое существование по сравнению с агрегированными компонентами.
Абстрактные классы и интерфейсы В этой главе мы обсуждаем абстрактные классы и интерфейсы. Мы исследуем концепцию интерфейсов как форму композиции и агрегации. Кроме того, мы углубляемся в абстрактные классы, которые допускают как абстрактные методы, так и обычные методы с логикой реализации.
Практическое использование интерфейсов Мы рассмотрим практические примеры интерфейсов, таких как интерфейс "Reader" с методом "read", интерфейс "Writer" с методом "write", а также их реализации в различных классах, таких как HTTP client, file reader и т.д. Гибкость, обеспечиваемая интерфейсами, позволяет создавать более универсальный код для достижения полиморфизма.
Проблемы внедрения и решения Здесь мы сталкиваемся с трудностями при реализации интерфейса из-за обобщенного характера, требующего объявления универсального типа. Мы решаем эти проблемы с помощью универсальных типов, которые обеспечивают гибкость при определении конкретных типов во время выполнения в рамках реализации нашего класса репозитория.
Внедрение зависимостей при разработке программного обеспечения Сегодня внедрение зависимостей имеет важное значение для создания программного обеспечения, основанного на принципах SOLID и шаблонах проектирования. Это предполагает разделение приложения на уровни, отвечающие за логику данных и бизнес-логику, при этом службы используют репозитории, не зная, какой конкретный репозиторий они используют.
Реализация теории внедрения зависимостей Теория, лежащая в основе внедрения зависимостей, сопровождается ее практической реализацией на примерах. Приложение разделено на уровни: один обрабатывает доступ к данным (например, операции с базой данных), а другой содержит бизнес-логику, которая может работать с различными типами репозиториев (например, MongoDB или MySQL). Сервисы используют интерфейсы для взаимодействия с репозиториями, что обеспечивает гибкость при изменении реализаций без изменения уровня сервиса.
Реальное применение внедрения зависимостей В реальном сценарии пользовательские интерфейсы репозитория реализованы специально для работы с базами данных MongoDB или PostgreSQL. Класс service содержит бизнес-логику, которая может использовать любой тип репозитория внутри, сохраняя при этом внешнюю конфигурируемость. Эта концепция позволяет тестировать различные реализации путем передачи соответствующих аргументов во время инициализации объекта.
Шаблон проектирования Singleton гарантирует, что создается только один экземпляр класса. Это полезно для сценариев, в которых несколько экземпляров могут вызывать проблемы, например, при подключениях к базе данных. Используя статические свойства и методы, мы можем получить доступ к классу без создания экземпляра.
В видео обсуждается концепция объектно-ориентированного программирования и шаблон Singleton, подчеркивается, что независимо от того, сколько объектов создано, они всегда будут давать один и тот же результат. Цель видео - объяснить фундаментальные принципы простым способом с реалистичными примерами.