Является ли принцип разделения интерфейса только заменой принципа единой ответственности? - PullRequest
26 голосов
/ 11 ноября 2011

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

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

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

Я прав?

Ответы [ 3 ]

29 голосов
/ 11 ноября 2011

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

18 голосов
/ 22 апреля 2013

Я думаю, что если мой класс выполняет SRP, нет необходимости извлекать больше чем один интерфейс.

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

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

Этот каскад абстракции будет происходить на протяжении всего вашего Car класса. Переместившись от самого Car вниз, вы обнаружите, что детализация увеличивается в каждом классе - например, в то время как класс Car может иметь метод changeGear(), позволяющий пользователю выбирать включенную передачу, класс Gearbox будет следить за тем, как это происходит (например, нажать на сцепление, отключить текущую передачу). выберите новую передачу и т. д.)

Однако при разработке ОО мы не хотим раскрывать детали нашего Gearbox конечному пользователю - мы хотим, чтобы они взаимодействовали с нашей системой на высоком уровне абстракции, без необходимости знать, как работают внутренние устройства. Работа. Мы также хотим ограждать эти внутренние компоненты, чтобы мы могли изменить их в будущем, не требуя от пользователей рефакторинга их кода (поэтому мы помечаем их как private или protected).

Из-за этого мы позволяем пользователям взаимодействовать с нашим автомобилем только через сам класс Car. Это , где вступает Принцип разделения интерфейса . SRP гарантирует, что класс Car делегирует свои подкомпоненты различным классам, но все наши методы public все равно будут вызывается через сам класс Car. ISP гарантирует, что вместо того, чтобы объединять все это вместе в одном интерфейсе, мы вместо этого создаем логические различия и выставляем несколько интерфейсов для связанной функциональности.

1 голос
/ 07 февраля 2016

номер

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

Предположим, что у вас есть 10+ различных возможностей, таких как Climb, Think, Learn, Apply. Класс Dog может иметь 2 возможности, а класс Cat может иметь 2 возможности, а класс Man может иметь 6 возможностей. Имеет смысл реализовать только применимые возможности в соответствующих классах.

Посмотрите на этот код.

public class ISRDemo{
    public static void main(String args[]){

        Dog dog = new Dog("Jack",16);
        System.out.println(dog);

        Learn dl = dog;
        dl.learn();
        ProtectOwner p = dog;
        p.protectOwner();

        Cat cat = new Cat("Joe",20);
        System.out.println(cat);
        Climb c = cat;
        c.climb();
        Remember r = cat;
        cat.doRemember();       

        Man man = new Man("Ravindra",40);   
        System.out.println(man);
        Think t = man;
        t.think();
        Learn l = man;
        l.learn();
        Apply a = man;
        a.apply();
        PlaySports pm = man;
        pm.playSports();
        Remember rm = man;
        rm.doRemember();

    }
}

class Dog implements Learn,ProtectOwner{
    private String name;
    private int age;
    public Dog(String name,int age){
        this.name = name;
        this.age = age;
    }

    public void learn(){
        System.out.println(this.getClass().getSimpleName()+ " can learn");
    }
    public void protectOwner(){
        System.out.println(this.getClass().getSimpleName()+ " can protect owner");
    }
    public String toString(){
        return "Dog :"+name+":Age:"+age;
    }
}
class Cat implements Climb,Remember {
    private String name;
    private int age;
    public Cat(String name,int age){
        this.name = name;
        this.age = age;
    }
    public void climb(){
        System.out.println(this.getClass().getSimpleName()+ " can climb");
    }
    public void doRemember(){
        System.out.println(this.getClass().getSimpleName()+ " can remember");
    }
    public String toString(){
        return "Cat :"+name+":Age:"+age;
    }
}
interface ProtectOwner {
    public void protectOwner();
}
interface Remember{
    public void doRemember();
}
interface Climb{
    public void climb();
}
interface Think {
    public void think();
}
interface Learn {
    public void learn();
}
interface Apply{
    public void apply();
}
interface PlaySports{
    public void playSports();
}

class Man implements Think,Learn,Apply,PlaySports,Remember{
    String name;
    int age;

    public Man(String name,int age){
        this.name = name;
        this.age = age;
    }
    public void think(){
        System.out.println(this.getClass().getSimpleName() + " can think");
    }
    public void learn(){
        System.out.println(this.getClass().getSimpleName() + " can learn");
    }
    public void apply(){
        System.out.println(this.getClass().getSimpleName() + " can apply");
    }
    public void playSports(){
        System.out.println(this.getClass().getSimpleName() + " can play sports");
    }
    public void doRemember(){
        System.out.println(this.getClass().getSimpleName() + " can remember");
    }
    public String toString(){
        return "Man :"+name+":Age:"+age;
    }
}

выход:

java ISRDemo
Dog :Jack:Age:16
Dog can learn
Dog can protect owner
Cat :Joe:Age:20
Cat can climb
Cat can remember
Man :Ravindra:Age:40
Man can think
Man can learn
Man can apply
Man can play sports
Man can remember

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

Взгляните на реализацию классов Dog, Cat and Man в том же примере.

...