Принцип разделения интерфейса с "необязательными" методами в реализации

Принцип разделения интерфейса от SOLID гласит, что классы не должны реализовывать / зависеть от методов, которые им не нужны. У тебя никогда не должно быть//Not used: just needed to implement interface в базе кода.

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

Скажем, у меня есть этот пример интерфейса:

Interface Input {
    Input create();
    void capitalizeInput(CAPITALIZATION cap);
    String getInput();
}

Class LatinInput implements Input {
    String input;
    Input create(String input){...}
    void capitalizeInput(CAPITALIZATION cap){...}
    String getInput(){...}
}

Class NumberOnlyInput implements Input {
    int input;
    Input create(int input){...}
    void capitalizeInput(CAPITALIZATION cap){
         // Needed because the interface requires it.
         return;
    }
    String getInput(){...}
}

Этот интерфейс широко используется в программе другими классами. В настоящее время в своих программах я делаю примерно следующее.

Class B {
    Input input;
    B(Input input){
       this.input = input;
    }

    String doStuff(){
        ...
        methodA();
        ...
        methodB();
        ...
        methodC();
        ...
        methodA();
        ...
        return ...;
    }

    private void methodA(){
        ...
        input.transformInput(CAPITAL);
        input.getInput();
    }

    private void methodB(){
        ...
        input.getInput();
    }

    private void methodC(){
        ...
        input.transformInput();
    }
}

И это называется классом C;

Class C {
    void doStuff() {
        List<A> list = new Arraylist<>();
        list.add(LatinInput.create("hello"));
        list.add(LatinInput.create("goodbye"));
        list.add(NumberOnlyInput.create(12345));

        for(Input input: list){
            B b = new B(a);
            b.doStuff();
        }
    }
}

Как мне изменить дизайн в соответствии с ISP, не меняя класс C, и при этом не нужно проверять, является ли объект instance of во время выполнения?

1 ответ

Решение

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

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

Здесь ничего не говорится о реализации методов с пустым телом. Твой классB использует оба capitalizeInput а также getInput, если это только два метода в Input, это не нарушает принцип разделения интерфейса. В твоем случаеB использует NumberOnlyInput.capitalizeInput так уж получилось, что empy body - допустимая реализация этой функции.

Однако, Input.create нарушает ISP. B зависит от Input но не использует Input.create- вообще не называется. В этом случае вы можете просто удалить его из интерфейса.

Вы все еще можете избавиться от этого странного пустого метода. посколькуNumberOnlyInput это частный случай LatinInput вы можете повторно использовать этот класс:

class NumberOnlyInput {
    static Input create(int input) {
        return new LatinInput(String.valueOf(input));
    }
}

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

Другие вопросы по тегам