我不清楚在选择要实例化的实现/子类时放置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();
}
}
但是我不知道界面是否知道它的实现,或者父类知道它的子类型是不是很糟糕。所以
答案 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完成了这项工作。还可以与依赖注入结合使用以增加效果。
这些至少是我能想到的。