【问题标题】:What is the alternative to static in java interfacejava接口中静态的替代方法是什么
【发布时间】:2015-02-23 10:36:18
【问题描述】:

我有一个设计问题。 我有一个读取 XML 的接口。每个实现者类都读取不同的 XML,我想要一种方法来确定我应该为我得到的 xml 类型动态创建哪个实现者。 问题是java接口不能有静态成员。最好的方法是什么?

例子:

public interface MyXML{
    public void readXML(String xml);
    public final static String getType();
}

用法:

func(String xml, String type)
    {
       MyXML obj;

       switch(type)
       {
          case MyImpl.getType():
             obj = new MyImpl();
             break;
         case MyImpl2.getType():
             obj = new MyImpl2();
             break;
      }
      obj.readXML(xml);
   }

编辑: 我将尝试更好地解释我想要的内容: 我需要知道哪个实现可以读取哪个 xml,并且我寻找一种方法来强制实现 MyXML 的任何人告诉它可以读取哪个 xml,这样我就不需要在另一个列表或工厂之外维护翻译。

【问题讨论】:

  • "MyImpl.getType()" 应该是常量,而不是在运行时动态评估。
  • 什么意思:Java接口不能有静态成员?接口中的所有变量都是静态的。
  • Stultuske: public final static String getType();对编译无效。

标签: java


【解决方案1】:

Java 只允许在接口中使用静态常量。在 Java 8 中,您还可以有默认实现,但这是另一回事。

解决这个问题的一种方法是使getType普通实例方法,与readXML相同,并提前实例化实现,像这样

// somewhere in the constructor or main
List<MyXML> readers = Arrays.asList(new MyImpl1(), new MyImpl2());

public MyXML findReaderForType(String type) {
  for (MyXML reader : readers) {
    if (reader.getType().equals(type)) {
      return reader;
    }
  }
}

但是,您需要谨慎设计实现方式,以便可以重复使用。

另一种选择是创建某种静态工厂,其中将包含等效于findReaderForType 方法。那么类型和实现的映射就包含在这个工厂类中了。

【讨论】:

    【解决方案2】:

    看看工厂设计模式。客户端应该调用工厂传递类型,然后工厂返回正确类的实例:

    public class MyFactory {
        public MyXML createMyXML(Type type) {
            return ...
        }
    }
    

    这样,客户就无需知道需要提供哪个具体类。

    【讨论】:

      【解决方案3】:

      在接口中存储实现类型是没有意义的。接口不应该知道实现。相反,您可以将 XML 类型存储在 Enum 中。

      enum Type{
      TYPE1,
      TYPE2;
      }
      

      然后您可以创建一个Map&lt;Type, MyXML&gt; 变量并在其中添加相应的Type 实现。

      工厂可以是这样的:

      public MyXml getImplementation(String type){
         Type type = Type.valueOf(type);
         MyXml impl= implementations.get(type);
         if(impl == null){
             throw new UnsupportedOperationException();//or whatever ex you see fit
         }
         return impl;
      }
      

      【讨论】:

      • 这是一个因扩展而关闭的系统。如果所有类型在编译时都是已知的,那么只需在 switch 语句中使用每个此类类型就足够了。在这两种情况下,设计都假设您可以完全控制所有 XML 阅读器类型,因此很容易确保每个阅读器类型都有静态变量。
      【解决方案4】:

      我建议你围绕实例设计你的系统,而不是类型本身。

      应用程序将实例化所有 XML 读取器类型,并查询每个实例以获取它负责的类型。您可以使用它将 XML 阅读器组织到一个地图中,并在没有 switch 或 if 语句的情况下检索它们。

      如果在您当前的设计中有一些重量级资源与某个实例相关联,请更改该设计,以便所有资源获取都发生在对象生命周期的后期,而不是在构建时。

      如果您一次需要同一个阅读器的多个实例(例如,在并发设置中),则使用java.util.regex.Pattern 及其对应的Matcher 示例的想法。模式是单线程一次性匹配器的线程安全工厂。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-01-28
        • 2012-01-12
        • 1970-01-01
        • 2012-12-20
        • 2023-04-09
        • 2010-12-25
        • 1970-01-01
        相关资源
        最近更新 更多