"optional" 方法在实现中的接口隔离原则

Interface Segregation Principle with "optional" methods in Implementation

SOLID 的接口隔离原则说 类 不应该 implement/depend 他们不需要的方法。你不应该有 //Not used: just needed to implement interface 在代码库中。

当一些方法本质上是 "optional" 时,我该如何应用这个原则,因为实现 class 是一个特定的极端情况。

假设我有这个界面示例:

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(){...}
}

该接口被其他 classes 在程序中广泛使用。目前在我的程序中,我正在做类似以下的事情。

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,而不更改 class C,同时也不需要在运行时检查对象是否 instance of

Interface segregation principle:

states that no client should be forced to depend on methods it does not use.

它没有说任何关于用空主体实现方法的事情。你的classB同时使用了capitalizeInputgetInput,只要是Input中的两个方法,就不会违反接口隔离原则。在您的情况下 B 使用 NumberOnlyInput.capitalizeInput 碰巧 empy body 是此功能的有效实现。

但是,Input.create确实违反了ISP。 B 依赖于 Input 但不使用 Input.create - 它根本没有被调用。在这种情况下,您可以将其从界面中删除。

你仍然可以摆脱那个奇怪的空方法。由于 NumberOnlyInputLatinInput 的特例,您可以重复使用 class:

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

它可能不太清晰或不太高效 - 这可能就是为什么首先创建数字的特殊情况。