在运行时选择一个具体的实现 Java 8
Choose a concrete implementation at runtime with Java 8
我不清楚在选择要实例化的 implementation/subclass 时将 if
/switch
放在哪里,特别是考虑到现在接口可以有静态方法时。
假设我有一个服务,一个由接口定义的类型和几个实现。我想最好不要把那个逻辑放在服务中,而是要有工厂方法。但是它应该按照 this answer 中的建议进入界面还是另一个带有参数到类型映射的 class?
把它放在界面中对我来说似乎很自然:
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();
}
}
但我不知道让接口了解其实现或父 class 了解其子类型是否不好。所以
- 我应该把那个逻辑放在哪里?
- 如果我选择某种类型的子class,情况会发生很大变化吗?
为此使用 Factory
。这样你就能维持single responsibility principle
。然而,在我自己的一个项目中,interface
定义了一种方法,该方法确定应该使用该特定实现的参数类型。由于这个和使用 Reflections
,整个过程是自动化的。 Reflections
查找所有实现给定 interface
的 classes 并将其 'usage-type' 存储在地图中以便快速查找。多亏了这样的解决方案,如果开发人员需要新的实现,他所要做的就是创建它。系统的其他部分不需要其他修改,甚至在工厂 class.
Reflections
具有在编译时存储元数据的良好功能,因此运行时查找正确的 classes 是一眨眼的功夫
你的问题有很多解决方案,我想你已经知道其中的很多了。
静态工厂方法模式
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 在这方面做得很好。还可以结合 依赖注入 来增加效果。
我能想到的就这些吧
我不清楚在选择要实例化的 implementation/subclass 时将 if
/switch
放在哪里,特别是考虑到现在接口可以有静态方法时。
假设我有一个服务,一个由接口定义的类型和几个实现。我想最好不要把那个逻辑放在服务中,而是要有工厂方法。但是它应该按照 this answer 中的建议进入界面还是另一个带有参数到类型映射的 class?
把它放在界面中对我来说似乎很自然:
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();
}
}
但我不知道让接口了解其实现或父 class 了解其子类型是否不好。所以
- 我应该把那个逻辑放在哪里?
- 如果我选择某种类型的子class,情况会发生很大变化吗?
为此使用 Factory
。这样你就能维持single responsibility principle
。然而,在我自己的一个项目中,interface
定义了一种方法,该方法确定应该使用该特定实现的参数类型。由于这个和使用 Reflections
,整个过程是自动化的。 Reflections
查找所有实现给定 interface
的 classes 并将其 'usage-type' 存储在地图中以便快速查找。多亏了这样的解决方案,如果开发人员需要新的实现,他所要做的就是创建它。系统的其他部分不需要其他修改,甚至在工厂 class.
Reflections
具有在编译时存储元数据的良好功能,因此运行时查找正确的 classes 是一眨眼的功夫
你的问题有很多解决方案,我想你已经知道其中的很多了。
静态工厂方法模式
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 在这方面做得很好。还可以结合 依赖注入 来增加效果。
我能想到的就这些吧