OOP, SOLID - Max-Starling/Notes GitHub Wiki

Основные принципы ООП

Некоторые определения

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

Класс — это описание еще не созданного объекта, как бы общий шаблон, состоящий из полей, методов и конструктора, а объект – экземпляр класса, созданный на основе этого описания.

Интерфейсы определяют некоторый функционал, не имеющий конкретной реализации, который затем реализуют классы, применяющие эти интерфейсы. Один класс может применить множество интерфейсов.

Инкапсуляция

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

Конечной целью является инкапсуляция тех вещей, которые не должны быть изменены. Лучше всего работает подход, при котором, у класса должна быть только одна причина для изменения, и инкапсулирование воплощает в реальность проектирование этой “одной причины”.

Преимущества инкапсуляции:

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

Пример: Пусть есть некая программа,в которой объекты общаются между собой в соответствии с установленными правилами. Объект самостоятельно управляет своим внутренним состоянием с помощью методов  — никто другой не может вызывать эти методы, если на это нет особого разрешения. Таким образом есть публичные (разрешённые) и приватные (неразрешённые) методы.

Абстракция

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

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

С помощью абстракции мы выделяем общее для всех объектов.

Преимущества абстракции:

  • Применяя абстракцию, мы можем отделить то, что может быть сгруппировано по какому-либо типу.
  • Часто изменяемые свойства и методы могут быть сгруппированы в отдельный тип, таким образом основной тип не будет подвергаться изменениям. Это усиливает принцип ООП: «Код должен быть открытым для Расширения, но закрытым для Изменений».

Пример: Представьте кофеварку. Когда она варит кофе, под ее корпусом творится много вещей. Но от вас требуется лишь насыпать кофе, налить воду и нажать кнопку.

Наследование

Наследование — это включение поведения (методов) и состояния (переменных) базового класса в производный класс, после чего они становятся доступными в производном классе.

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

Наследование — это форма повторного использования ПО, когда из уже существующего класса (суперкласса) создается новый класс (подкласс), который использует некоторые свойства суперкласса и при этом имеет дополнительные характеристики.

Преимущества наследования:

  • Переиспользование кода.
  • Избежание дублирования кода
  • Устанавливается логическое отношение «is a». Например: Dog is an animal.
  • Модуляризация кода.

Недостаток:

  • Сильная связанность кода.

Полиморфизм

На греческом, полиморфизм означает «многообразие форм».

Полиморфизм в программировании — это способность предоставлять один и тот же интерфейс для различных типов данных.

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

Полиморфизм позволяет использовать объекты с одинаковыми характеристиками в разных направлениях.

Общие свойства объектов объединяются в систему, которую могут называть по-разному  —  интерфейс, класс.

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

Примечание: Полиморфизм — это способность выбирать более конкретные методы для исполнения в зависимости от объекта. Полиморфизм осуществляется тогда, когда не задействованы абстракные классы.

Преимущества полиморфизма:

  • Создание повторно используемого кода. То есть, как только класс создан, реализован и протестирован, он может свободно использоваться без заботы о том, что конкретно в нем написано.
  • Универсальность и слабосвязанность кода.
  • Динамическое связывание.
  • Один и тот же интерфейс может быть использован для создания методов с разными реализациями.

Композиция

Повторное использование кода может быть достигнуто с помощью как наследования, так и композиции. Но при этом задействование композиции обеспечивает более высокий уровень инкапсуляции, чем наследование, так как изменения в back-end классе не обязательно затронут код, который относится к front-end классу.

Композиция — это техника проектирования, применяющая в классах отношения типа “has-a” (имеет, включает в себя). Для повторного использования кода могут применяться как наследование в java, так и композиция объекта.

Суть композиции заключается в выражении отношения "has a" между объектами. Подумайте о стуле. У стула есть (has a) сидение. У стула есть (has a) спинка. У стула есть (has a) определенное количество ножек. Фраза ”has a” / “есть” предполагает отношения, в которых стул имеет или, как минимум, использует другой объект. Это как раз и есть отношения “has-a”, являющиеся основой композиции.

Преимущества композиции:

  • Контроль видимости.
  • Реализация может быть заменена во время выполнения (run-time)
  • Слабая связанность, так как класс-интерфейс не зависит от реализации.

Примечание: Не используйте наследование только для того, чтобы обеспечить повторное использование кода. Если нет отношенией “is a“ (является), для этих целей используется композиция.

Абстракция vs Инкапсуляция

Инкапсуляция — это стратегия, используемая как часть абстракции. Инкапсуляция относится к структуре объекта: объекты инкапсулируют свои свойства и скрывают их от доступа извне. Пользователи класса взаимодействуют с ним с помощью его методов, но не имеют доступа напрямую к структуре класса. Таким образом класс абстрагирует детали реализации, относящиеся к его строению.

Абстракция является более общим термином. Она также может достигаться среди прочего с помощью подклассов.

Часто абстракция невозможна без сокрытия основного состояния с помощью инкапсуляции. Если класс раскрывает свою внутреннюю структуру, он не может изменить свои внутренние операции, а, следовательно, не может абстрагироваться.

Подробнее:
https://javarush.ru/groups/posts/1880--principih-oop
https://javarush.ru/groups/posts/1265-koncepcii-obhhektno-orientirovannogo-programmirovanija-java
https://medium.com/nuances-of-programming/%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D0%B5-%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%B4%D0%BB%D1%8F-%D1%81%D0%B0%D0%BC%D1%8B%D1%85-%D0%BC%D0%B0%D0%BB%D0%B5%D0%BD%D1%8C%D0%BA%D0%B8%D1%85-b0e0578761f1
https://medium.com/webbdev/solid-4ffc018077da