【问题标题】:Java Interface - constants and static class in normal interfaceJava 接口 - 普通接口中的常量和静态类
【发布时间】:2013-08-16 04:33:21
【问题描述】:

考虑以下界面。

public interface ThirdPartyApiHandler {

    public OperationResult doOperation(OperationInput input);

    public static class OperationResult {
         //members of OpeationResult. metrics after file processing
         private int successfulRecords;
         private int failedRecords;
    }  

    public static class OperationInput {
         //implementations call third party API to process this file.
         private String inputBatchFile; 
    }  

    //Constant which would be same across all implementations.
    public static final int GLOBAL_CONSTANT = 1;
}

上面的界面是不是设计不好?

  1. OperationResultOperationInput 被定义为静态类。它们只会被实现使用,而不是其他任何地方。我在这里看到的优势是 - 我不必为这两个类创建单独的文件。他们还获得父类的命名空间。

  2. 我已阅读有关常量接口的信息。但在这种情况下,我在普通接口中定义常量,这些常量在所有实现中都是相同的,并且将在这些实现中使用。

我是第一次使用这种模式,所以想得到建议。

【问题讨论】:

  • 您的OperationResultOperationInput 中有什么内容?
  • OperationInput 包含用于调用第三方 API 的成员变量。 OperationResult 是我的包装器,它将第三方 API 结果转换为可用格式。
  • @Jitendra。你能完成你问题中的那些课程吗?以便我们能够想到合适的设计。
  • OperationResult and OperationInput are defined as static inner class. They won't be used anywhere else 但如果你实现了doOperation 方法。这个方法的调用者会使用这两种类型,不是吗?
  • 是的,我的意思是,它们只会用于这个特定接口的实现。不是任何其他不相关的类。

标签: java


【解决方案1】:
Is above interface a bad design?

很简单,是的。

any 逻辑放在 interface 中在语义上是不正确的。接口向消费者公开功能 - 这是它的单一目的,不应被淡化。

考虑在基实现类中实现任何通用功能并使用继承,或者在一个或多个服务中并使用组合,在您的不同接口实现中。

编辑 - 引用 Joshua Bloch 的 Effective Java

当一个类实现一个接口时,该接口充当一种可用于引用该类实例的类型。因此,一个类实现了一个接口应该说明客户端可以对类的实例做什么。为任何其他目的定义接口是不合适的。

【讨论】:

  • @downvoter - 你认为这个答案的哪个方面没有用?
  • 我不是反对者,但...that is it's single purpose... 这不是 100% 正确的。例如标记界面。
  • 我真的不明白你的意思,因为标记接口实际上只是向消费者公开功能的一种特殊情况,除了该功能不需要任何方法即可实现,例如'Serializable ' 在 Java 中。添加了来自 Joshua Bloch 的“Effective Java”的引用,它支持我的观点。
【解决方案2】:
Is above interface a bad design?

这取决于您的实现设计及其在项目中的可用性。逻辑在我看来都是合法的。这种设计的可能用例如下

public interface A {
    static class B {
        public static boolean verifyState( A a ) {
            return (true if object implementing class A looks to be in a valid state)
        }
    }
}

还有

public static class OperationResult {
     //members of OpeationResult. metrics after file processing
     private int successfulRecords;
     private int failedRecords;
} 

在上面的类中,你有实例变量successedRecords 和 failedRecords 。为什么不将这些静态类的实例变量设为静态,以便您可以使用 ThirdPartyApiHandler.OperationResult.successfulRecords 访问它们。您甚至可以为变量设置静态 getter 和 setter。


OperationResult and OperationInput are defined as static inner class.

与流行的看法相反,没有“静态内部类”这样的东西:这根本没有意义,当嵌套类是静态的时,没有“内部”和“外部”类,所以它不能是“静态内部” ”。

this SO 问题中摘录。阅读第一个答案。我想这会回答你所有的问题。

【讨论】:

  • 好吧,这个答案如何解决真正的问题?您只是在评论 OP 使用的术语,既然您在评论,这应该是真正的评论。
  • 你说的“所有实现接口的子类都将共享同一个类”是什么意思?静态类的实例成员仍然是实例成员——它们不会在静态类的所有实例之间共享!
【解决方案3】:

在接口中拥有嵌套类只是额外命名空间的问题。当创建小接口以支持简单的数据结构时,这种方法有助于组织代码。

我推荐你这个讲座:Java Tip 75: Use nested classes for better organization

请注意,publicstatic 在这种情况下是多余的,因此您不需要它们。您需要记住的是,拥有这样的类不会限制其他开发人员在代码的其他部分使用它们。

从我的角度来看,这是一个很好的设计,但是我会用接口扩展和替换类。

public interface ThirdPartyApiHandler {

    OperationResult doOperation(OperationInput input);

    interface OperationResult {
         int getSuccessfulRecords();
         int getFailedRecords();
    }  

    interface OperationInput {
         String getInputBatchFile(); 
    }  

    final int GLOBAL_CONSTANT = 1; //This could be replaced by enum but no need 
}

【讨论】:

    【解决方案4】:

    OperationResult 和 OperationInput 被定义为静态内部类。 它们不会在其他任何地方使用。

    没关系,因为它们不会在其他任何地方使用。如果它们比我更愿意将它们放在单独的类中。

    我已经阅读了关于常量接口的内容。但在这种情况下,我在普通接口中定义常量,这些常量绑定在所有实现中都相同,并且将在这些实现中使用。

    这是声明这样一个字段的好地方。

    【讨论】:

    • 常量接口反模式更具体地指不声明任何方法并且仅用于向实现它的应用程序提供全局常量的接口。您对常量的使用非常合适。
    • @Tala,我更新了我的问题。 They won't be used anywhere else。我的意思是,它们显然会被所有实现使用,并且在使用实现中定义的doOperation 方法的类中会有一些引用。
    • 接口不是为所有实现放置常量共享的地方。接口应该只声明合同。当然,除非真正的意图是声明常量供外部客户端使用。我还没有看到有人使用接口与客户端共享常量。它被视为通过接口泄漏实现细节。
    猜你喜欢
    • 1970-01-01
    • 2010-09-24
    • 2017-12-05
    • 2023-03-16
    • 2020-03-22
    • 2013-10-09
    • 2014-01-01
    • 2014-06-02
    相关资源
    最近更新 更多