使用Java 8在运行时选择具体实现

时间:2015-03-20 15:42:17

标签: java inheritance interface-implementation

我不清楚在选择要实例化的实现/子类时放置if / switch的位置,特别是考虑到现在接口可以有静态方法。

假设我有一个服务,一个由接口和几个实现定义的类型。我想最好不要把这个逻辑放在服务中,而是要有工厂方法。但是它应该在界面中还是在另一个类中使用this answer中建议的param-to-type映射?

将它放在界面中似乎很自然:

public interface MyInterface
{
    public void doSomething();

    public static MyInterface create(int param)
    {
        if (param == 0)
            return new ImplA();
        else
            return new ImplB();
    }
}

然后只需从服务中调用它:

public class MyService
{
    public void serveMe(int param)
    {
        MyInterface.create(param).doSomething();
    }
}

但是我不知道界面是否知道它的实现,或者父类知道它的子类型是不是很糟糕。所以

  1. 我应该把这个逻辑放在哪里?
  2. 如果我选择某种类型的子类,会改变很多吗?

2 个答案:

答案 0 :(得分:7)

使用Factory。这样您就可以维护single responsibility principle。在我自己的一个项目interface中,定义了一种方法,用于确定应使用此特定实现的参数类型。由于这一点并使用Reflections,整个过程是自动化的。 Reflections找到实现给定interface的所有类,并将其“usage-type”存储在地图中以便快速查找。感谢这样的解决方案,如果他需要新的实现,所有开发人员必须做的就是创建它。系统的其他部分不需要进行其他修改,甚至在工厂类别也不需要。

Reflections具有很好的功能,可以在编译时存储元数据,因此运行时查找正确的类只是一眨眼

答案 1 :(得分:2)

你的问题有很多解决方案,我想你已经了解了很多问题。

静态工厂方法模式

interface Interface {
    public static Interface create(...);
}

这有效,但它使界面和实现的分离变得困难。接口必须知道所有可能的实现,并且它不是特别可扩展的。要添加新实现,您需要更改界面。

工厂模式

GOF这本书或多或少老派:

interface Factory {
    public Interface create(...)
}

这允许您替换工厂(甚至堆栈工厂)。它有 - 但是 - 你需要传递工厂对象的缺点。请注意,使用Java 8,您还可以使用非常轻量级的基于lambda的工厂(请参阅https://docs.oracle.com/javase/8/docs/api/java/util/function/Supplier.html

<强>集装箱

另一个解决方案,虽然它可以是非常重量级的,但是将对象的构造留给容器框架。在这些情况下,容器提供对象工厂。实际的对象类型留给配置。 Spring和Java EE完成了这项工作。还可以与依赖注入结合使用以增加效果。

这些至少是我能想到的。