Принцип разделения интерфейсов (ISP) гласит, что класс не должен быть вынужден реализовывать интерфейсы, которые он не использует. Другими словами, класс должен иметь конкретный и целенаправленный интерфейс, включающий только те методы, которые имеют отношение к его поведению.

Аналогия

В классе есть два человека по имени Мира и Эки. Оба спортсмены. Мира — пловчиха, а Эки — бегун. Им обоим, как спортсменам, необходимы упражнения и практика.

Несмотря на то, что они оба спортсмены, их тренировки разные, потому что их виды спорта разные. Мира определенно сосредоточится на упражнениях по плаванию, а Эки - на беговых упражнениях. Единственная разница между ними заключается в том, где они тренируются. Однако это не означает, что сходства нет. Оба должны растянуться перед началом тренировки.

Какова связь между этим и принципом разделения интерфейса?

Давайте рассмотрим это в контексте программирования. Мы можем представить, что и Мира как пловчиха, и Эки как бегун являются спортсменами. Они оба тренируются/упражняются. В программировании есть термин «Интерфейс». Интерфейс подобен контракту, который должен выполнить класс. Итак, мы можем связать, что существует интерфейс Athlete с контрактом, содержащим существующие упражнения.

Затем есть класс Runner, представляющий бегуна, и класс Swimmer, представляющий пловца. Оба они реализуют интерфейс Athlete.

Пока вы понимаете, что что-то не так? Если да, поздравляю! Проблема этой реализации в том, что она неэффективна и неточна. Несмотря на то, что Бегун действительно бегает и разминается, это не означает, что его можно объединить с Пловцом, который плавает и разминается, в одном интерфейсе.

Чтобы это исправить, нам нужно реализовать принцип разделения интерфейса. Принцип разделения интерфейсов гласит, что класс не должен быть вынужден реализовывать интерфейсы, которые он не использует. Таким образом, класс Runner не следует заставлять реализовывать метод swim(), а класс Swimmer не следует заставлять реализовывать метод run().

Итак, как нам это исправить? Давай подумаем. Плавание – это категория водного спорта. Все водные виды спорта требуют плавания, поэтому имеет смысл создать такой интерфейс. То же самое и с бегуном, который представляет собой наземный вид спорта, требующий бега. Мы можем создать два новых интерфейса: интерфейс наземного спорта и интерфейс водного спорта. Класс Runner будет включать методы run() и warmUp(), а класс Swimmer — методы swim() и warmUp().

Как это применяется в реальном случае разработки программного обеспечения?

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

Как бы мы это спроектировали? Начнем с его разработки без применения ISP. Все эти три вещи — предметы в библиотеке. Итак, мы можем создать интерфейс под названием Item. Ее можно взять, вернуть и прочитать на месте. Дизайн будет такой:

Книги, журналы и газеты будут классами, реализующими этот интерфейс.

Однако этот дизайн нарушает принцип разделения интерфейса. Принцип разделения интерфейсов гласит, что класс не должен быть вынужден реализовывать интерфейсы, которые он не использует. Например, газета является библиотечным предметом, но ее нельзя взять напрокат. Таким образом, не следует принудительно реализовывать методы кредита() и возврат().

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

Мы можем разделить интерфейс элемента библиотеки на читаемый и заимствуемый интерфейсы. По своим основным целям.

После разделения интерфейсов классы теперь могут реализовывать те интерфейсы, которые им нужны. Book и Magazine могут брать, возвращать и читать, поэтому они реализуют интерфейсы Readable и Borrowable. Газету можно только читать, поэтому она будет реализовывать только интерфейс Readable.

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

Поздравляем!

Добро пожаловать в конец урока! Поздравляю с тем, что уже многому научился.

Сначала вы узнаете о принципе разделения интерфейсов (ISP), одном из принципов SOLID. ISP утверждает, что класс не следует заставлять реализовывать интерфейсы, которые он не использует.

Во-вторых, вы узнаете, как работает ISP, используя аналогию со спортсменами.

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

Вы все еще в замешательстве?

Возможно, объяснение этой концепции до сих пор оставило у вас много вопросов. Но поверьте, это нормально. Вы поймете это со временем. Чтобы понять эту концепцию, вам также необходимо знать ее реализацию в коде. Для этого я написал еще одну статью специально о реализации кода. Вы можете получить к нему доступ через: https://mrezkys.medium.com/interface-segregation-principle-i-in-solid-practical-with-swift-d90c005ec147

От писателя

Здравствуйте, разрешите представиться — я Мухаммад Резкий Сулихин. Мы подошли к концу этой статьи, и я искренне благодарю вас за то, что нашли время ее прочитать. Если у вас есть какие-либо вопросы или отзывы, свяжитесь со мной напрямую по электронной почте [email protected]. Я более чем рад получить ваше мнение, будь то мои навыки письма на английском языке или что-то еще, я могу ошибаться. Ваши идеи помогут мне расти.

С нетерпением ждем возможности связаться с вами в будущих статьях! Кстати, я мобильный разработчик, сейчас учусь в Apple Developer Academy. Я открыт для различных возможностей, таких как сотрудничество, внештатная работа, стажировки, неполный или полный рабочий день. Для меня было бы огромным счастьем изучить эти возможности.