2017-06-02 62 views
0

我有一个类型列表。我想找到一个有资格处理不同价值的特定类。如何通过其方法实现动态地找到类?

在以下示例中,每个实现必须提供supports(String)方法。并定义这个类支持哪些值。

问题:我没有对象在列表中,但分类型。因此我不能在其上调用自定义方法,如supports()

List<Class<MyService>> list; 

public Object getInstanceThatSupports(String val) { 
    val = "TEST"; 

    for (Class<MyService> c : list) { 
     if (c.supports(val)) { //TODO this is invalid 
      return c.newInstance().process(val); 
     } 
    } 
} 

public interface MyService { 
    boolean supports(String val); 
    void process(String val); 
} 

public class MyServiceImpl implements MyService { 
    @Override 
    public boolean supports(String val) { 
     return val.equals("TEST"); 
    } 

    @Override 
    public void process(String val) { 
     //handle the value 
    } 
} 

我该怎么做到这一点?

+0

使用反射可以的方式,但它不是很清楚你想要什么 – Jens

+0

那么。如果我的输入值是'TEST',我想找到支持该值的'MyService'实现。它由'supports(val)'方法定义。但是我不能在类型上调用这个方法,所以我找不到这种方法。 – membersound

+0

您可以创建一个新实例并将其称为'c.newInstance()。supports(“TEST”);' – Jens

回答

1

例如,您可以创建一个注释@Supports,例如您可以使用注释来实现注释。

这个注释可能看起来像这样:

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.TYPE) 
public @interface Supports { 

    String value(); 
} 

通过使用Class.isAnnotationPresent你可以请检查是否或不实施具有neede注释和使用Class.getAnnotation你得到的注解,并且可以访问value()方法来获得支持值。

+0

我曾经猜测'supports()'做的不止是'return value.equals(SOME_CONSTANT)'。我想我猜错了。 – slim

2

,因为你需要调用的所有元素的方法列表

List<MyInterface> list = Arrays.asList(new MyImpl(), new MyImpl2()); 
String val = "TEST"; 

for (MyInterface x : list) { 
    if (x.supports(val)) { 
     //TODO 
    } 
} 
+0

不幸的是,我需要在每次执行时都提供一个新的服务实例。所以我不能把服务实例放入列表中。我无法重用它们。 – membersound

+0

好吧,让我检查! –

1

你问什么不能做,因为你的MyService的API,你应该做的,而不是List<MyInterface>

只有找出给定类是否支持字符串值的方法是调用supports()这是一种非静态方法。所以你必须创建一个实例才能调用它。

Java不允许您在接口中定义静态方法。

我的建议是不要打这个,并将其作为您的设计出现问题的指示。你会更好而不是有一个列表Class<?>,而是有一个列表MyInterface。使它们成为无状态和可重入的,然后您可以轻松地拨打supports()process()

for(MyInterface obj : objs) { 
    if(obj.supports(s)) { 
     obj.process(s); 
    } 
} 

这是一个非常常见的模式,特别是像Spring这样的框架。您将在初始时创建MyInterface对象的列表,并在程序的整个生命周期中重新使用它。

如果必须每次创建新实例,创建为每一个相应的工厂对象,而不是一个类型列表,有MyInterfaceFactory列表:

public class MyInterfaceImplFactory implements MyInterfaceFactory { 
    public boolean supports(String s) { 
     // hard code this here 
    } 

    public MyInterfaceImpl newInstance() { 
     return new MyInterfaceImpl(); 
    } 
} 

...

for(MyInterfaceFactory factory : factories) { 
    if(factory.supports(s)) { 
     MyInterface obj = factory.newInstance(); 
     obj.process(s); 
    } 
} 

(如果你有这么多写这些的人会变得重复性的,你可以更动态地做到 - 但以愚蠢的方式开始)。


如果你确定有类的列表,你可以在运行时检查:

  • ,你可以对其他没有在接口中声明静态supports()方法标准化。你必须通过Reflection来调用它,并且不需要Java的类型安全性。
  • 你也许能够做一些定制的注解

但不要做任何的这些,如果您有任何自由。

+0

好吧,我得到所有类定义该接口。但我实际上并没有执行接口方法'supports()'。但这是至关重要的,因为此方法定义了是否可以使用该实现。 – membersound

+0

我对这个问题表示歉意,我已经完全重写了这个。 – slim