接口隔离原则 - Java

时间:2017-09-25 15:12:18

标签: java design-patterns coding-style

我有一个界面

interface XXXCommandHandler(){
    void parse(String something);
    String response();
    String additionalResponse();
}
  1. 实现XXXCommandHandler的一些类不实现additionalResponse()。
  2. 我正在使用ApplicationContextManager.getInstance()。getBeansOfType(XXXCommandHandler.class)来获取实现XXXCommandHandler的类
  3. 然后调用parse,response和additionalResponse
  4. 由于有些人没有实现additionalResponse,我被迫返回null。
  5. 我可以想到以下

    1. 不要在没有实现additionalResponse的类上返回null,而是将additionalResponse声明为default方法并返回null /或使其返回Optional etc并在实现additionalResponse方法的类上覆盖它。
    2. 丑陋的方式: - 在所有未实现additionalResponse的类中返回null
    3. 使用解析和响应方法创建两个不同的接口XXXCommandHandlerParser(),使用扩展XXXCommandHandlerParser的additionalResponse方法创建XXXCommandHandlerAddtionalresponse(),即

      interface XXXCommandHandlerParser(){

          void parse(String something);
          String response();
      
      }
      

      interface XXXCommandHandlerAddtionalresponse() 扩展XXXCommandHandlerParser {

          String additionalResponse();
      }
      
    4. 但如果我做#3,我必须改变 ApplicationContextManager.getInstance()。getBeansOfType(XXXCommandHandlerAddtionalresponse.class)。

    5. 如果我执行#4,则不会选择未实现additionalResponse或未实现XXXCommandHandlerAddtionalresponse的类。
    6. 你能想到任何优雅的方式吗?

3 个答案:

答案 0 :(得分:0)

这是一个品味问题,哪种解决方案更优雅,但至少还有一种方法:

  1. 创建顶级界面:interfaceA

  2. 使用额外的方法将interfaceA扩展到interfaceB。

  3. 收集interfaceA

  4. 类型的bean
  5. 如果实例是interfaceB而不是强制转换,则调用额外的方法。

  6. 也许它没有比返回可选的默认实现更优雅。

答案 1 :(得分:0)

根据“additionalResponse”的含义,可以在基本接口中声明它,将一个返回null(或一个空String?)的实现添加到基本实现中,并将实际实现添加到相应的子类中。 / p>

在现实世界中,通常会考虑另一位开发人员是否会对您计划的实施感到惊讶,并因此可能以导致错误的方式使用它。

如果你想要看中,Decorator Pattern可能是候选人。

虽然子类化通常不受模式大师的欢迎,因为它经常使用而不是合理使用,这是人们所知道和期望的。这将是@Zsolt V推荐的解决方案(这里是伪代码 - 可能无法编译):

Collection<XXXCommandHandler> baseHandlers = ApplicationContextManager.getInstance()
  .getBeansOfType(XXXCommandHandler.class).values();
for (XXXCommandHandler baseHandler: basehHandlers) {
  baseHandler.parse(something);
  baseHandler.response();

  if (baseHandler instanceof XXXCommandHandlerAddtionalresponse.class) {
    XXXCommandHandlerAddtionalresponse additionalResponseHandler
      = (XXXCommandHandlerAddtionalresponse) baseHandler:
    additionalResponseHandler.additionalResponse();
  }
}

答案 2 :(得分:0)

我也会尽力帮助你。从我的角度来看,您可以创建一个接口或直接类Response并返回它而不是String。在那里你可以添加方法supportsAdditionalResponse并在获得additionalResponse之前检查它。如果不支持additionalResponse,则抛出getAdditionalResponse方法UnsupportedOperationException。

从我的角度来看,ApplicationContextManager.getInstance()。getBeansOfType(XXXCommandHandler.class)也不是一件好事,因为你暴露了你的基础设施。如果可能的话,更好的方法是添加方法List getCommandHandlers()。

   public interface Response {
     String getResponse();

     default Boolean supportsAdditionalResponse() {
       return false;
     };

     default String getAdditionalResponse() {
       throw new UnsupportedOperationException();
     }
   }


   public class HttpResponse implements Response {
    private String response;

     public HttpResponse(String response) {
      this.response = response;
     }

    @Override
    public String getResponse() {
      return response;
    }

  }

  public interface CommandHandler {
    void parse(String command);
    Response getResponse();
  }

  public class HttpCommandHandler implements CommandHandler {
    private final Response response;

    public HttpCommandHandler(Response response) {
     this.response = response;
    }

    @Override
    public void parse(String command) {
     //do smth
    }

    @Override
    public Response getResponse() {
      return response;
    }
 }