Рубрики
Без рубрики

твердый: Принцип разделения интерфейсов

Этот принцип был разработан Робертом К. Мартином во время работы в Xerox в качестве консультанта. Мартин был… С тегами java, ооп, программирование, архитектура.

ТВЕРДЫЕ Принципы (Серия из 5 частей)

Этот принцип был разработан Робертом К. Мартином во время работы в Xerox в качестве консультанта. Мартин отвечал за разработку новой системы управления печатью, которая могла выполнять задачи одновременно, что было новым для того времени.

Разрабатывая эту новую систему печати, Мартин заметил, что небольшие изменения в дизайне привели к масштабному развертыванию. В некоторых тех же случаях это приводило к развертыванию модулей, выходящих за рамки изменения. Проблема была в основном вызвана большим интерфейсом fat, используемым во всех модулях системы.

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

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

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

Типичное нарушение Принципа

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

Новые принтеры обеспечивают следующие возможности:

  • Печатание
  • Сканирующий
  • Отправка факса

Вы определяете интерфейс Все в одном принтере LX для моделирования основных задач, которые может выполнять новый принтер.

public interface AllInOneLXPrinter {


    public boolean print();

    public boolean scan();

    public boolean fax();
}

Вы определяете свой первый класс принтера следующим образом.

public class LX8578Printer implements AllInOneLXPrinter {

    @Override
    public boolean print() {
        //Logic for printing 
        return true;
    }

    @Override
    public boolean scan() {
        //Logic for scanning
        return true;
    }

    @Override
    public boolean fax() {
        //Logic for faxing
        return true;
    }

}

Пожалуйста, примите во внимание, что любой из этих классов имеет реальную реализацию. Они просто используются для упрощения примера.

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

Учитывая, что этот новый принтер будет продаваться под тем же брендом, вы решите использовать тот же интерфейс.

Вы определяете следующий класс для нового экономического принтера.

public class LX8590Printer implements AllInOneLXPrinter {

    @Override
    public boolean print() {
        //Logic for printing
        return true;
    }

    @Override
    public boolean scan() {
        //Logic for scanning
        return true;
    }

    @Override
    public boolean fax() {
        throw new UnsupportedOperationException("Faxing not supported."); 
    }

}

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

Соблюдение принципа разделения интерфейсов

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

  • Все В Одном Факсе
  • Все В Одном Сканировании
  • Печать “Все В Одном”
public interface AllInOneFaxing {

    public boolean fax();
}

public interface AllInOnePrinting {

    public boolean print();
}

public interface AllInOneScanning {

    public boolean scan();
}

Мы модифицируем первый класс принтера _ LX8578Printer _ , чтобы он мог использовать специализированные интерфейсы.

public class LX8578Printer implements AllInOnecanning, 
        AllInOneFaxing,
        AllInOnePrinting{

    @Override
    public boolean print() {
        //Logic for printing
        return true;
    }

    @Override
    public boolean scan() {
        //Logic for scanning
        return true;
    }

    @Override
    public boolean fax() {
        //Logic for faxing
        return true;
    }

}

Теперь мы можем определить наш LX8590Printer без зависимости от какого-либо метода, который никогда не будет использоваться.

public class LX8590Printer implements AllInOneScanning, 
        AllInOnePrinting{

    @Override
    public boolean print() {
        //Logic for printing
        return true;
    }

    @Override
    public boolean scan() {
        //Logic for scanning
        return true;
    }

}

Сейчас наше решение соответствует принципу разделения интерфейсов.

Разница между Принципом разделения интерфейса и принципом замещения Лискова

Некоторые разработчики могут запутаться, пытаясь найти различия между интернет-провайдером и интернет-провайдером, но они совершенно разные. LSP фокусируется на соблюдении контракта, установленного абстрактным классом, с помощью подтипов и наследования. С другой стороны, он ориентирован на разделение интерфейсов fat на специализированные интерфейсы, поэтому класс не будет зависеть от интерфейсов, которые не будут использоваться.

Когда использовать принцип разделения интерфейсов

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

Если вы хотите узнать больше об интернет-провайдере, вы можете заглянуть в Блог дяди Боба .

ТВЕРДЫЕ Принципы (Серия из 5 частей)

Оригинал: “https://dev.to/victorpinzon1988eng/solid-interface-segregation-principle-31c2”