4. ISP (Interface segregation principle) - Принцип разделения интерфейса

Принцип разделения интерфейса (англ. Interface Segregation Principle, ISP) один из пяти принципов проектирования классов в объектно-ориентированном программировании. Следование этому принципу помогает системе оставаться гибкой при внесении изменений в логику работы и пригодной для рефакторинга.

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

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

Используем наш пример с фигурами. Например, у нас есть твердые фигуры и мы бы хотели иметь возможность вычислять их объем.

Для этого нам нужно добавить еще один контракт в интерфейс ShapeInterface:

interface ShapeInterface {
     public function area();
     public function volume();
}

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

Следуя принципу ISP, мы можем создать второй интерфейс, который может называться SolidShapeInterface и иметь метод вычисления объема. Твердые фигуры, такие как кубы, могут использовать этот интерфейс:

interface ShapeInterface {
     public function area();
}
 
interface SolidShapeInterface {
     public function volume();
}
 
class Cuboid implements ShapeInterface, SolidShapeInterface {
     public function area() {
         // calculate the surface area of the cuboid
     }
 
     public function volume() {
         // calculate the volume of the cuboid
     }
}

Это более лучшее решение, но есть ловушка с использованем проверки типа (type-hinting) этих интерфейсов вместо использования ShapeInterface или SolidShapeInterface.

Можно создать другой интерфейс, например ManageShapeInterface, и использовать его для всех типов фигур (плоских и объемных). Таким образом можно увидеть ,что он имеет единый API для управления всеми фигурами:

interface ManageShapeInterface {
     public function calculate();
}
 
class Square implements ShapeInterface, ManageShapeInterface {
     public function area() { /*Do stuff here*/ }
 
     public function calculate() {
         return $this->area();
     }
}
 
class Cuboid implements ShapeInterface, SolidShapeInterface, ManageShapeInterface {
     public function area() { /*Do stuff here*/ }
     public function volume() { /*Do stuff here*/ }
 
     public function calculate() {
         return $this->area() + $this->volume();
     }
}

Теперь в классе AreaCalculator мы можем заменить вызов метода рассчета и проверки объекта на пренадлежность к интерфейсам ManageShapeInterface, но не ShapeInterface.

Теги: Solid, Isp, Interface segregation principle, Принцип разделения интерфейса


Похожие статьи

1. SPR (Single responsibility principle) - Принцип единственной обязанности

2. OCP (Open/closed principle) - Принцип открытости/закрытости

5. DIP (Dependency inversion principle) - Принцип инверсии зависимостей

3. LSP (Liskov substitution principle) - Принцип подстановки Барбары Лисков