java - 如何为许多具体类型创建抽象工厂
问题描述
假设我们有一个名为 的接口IAction
,并且有很多类(超过 20 个)实现了这个接口:ConreteAction1
、ConreteAction2
等。所有这些类都有带参数的构造函数。此外,所有这些类以及它们的依赖项都在 Dagger 模块中注册(作为瞬态对象或单例)。我们的任务是实现(或自动生成)抽象工厂实现接口,类似于:
public interface IActionFactory{
IAction createByClass(Class clazz); // create action by type
// or
IAction createByName(String name); // create action by custom name
}
我知道如何使用 Dagger 对Provider<T>
注释的支持来实现这个工厂:
public class ActionFactory implements IActionFactory{
@Inject Provider<ConcreteAction1> concreteAction1Provider;
@Inject Provider<ConcreteAction2> concreteAction2Provider;
(...)
@Override
public IAction createByClass(Class clazz){
if(ConcreteAction1.class.equals(clazz)){
return concreteAction1Provider.get()
}
if(ConcreteAction2.class.equals(clazz)){
return concreteAction2Provider.get()
}
(...)
}
@Override
public IAction createByName(String name){
if(name.equals("name_1")){
return concreteAction1Provider.get()
}
if(name.equals("name_2")){
return concreteAction2Provider.get()
}
(...)
}
}
不幸的是,这种方法涉及大量样板代码(我有 20 多个具体类),并且每次创建另一个IAction
接口实现时都必须修改上面的工厂(违反 Open-Close 原则)。
Dagger 中是否有任何其他方式可以以更优雅和可扩展的方式创建这样的工厂实现?
解决方案
您可以为此使用多重绑定。
@Module public interface ActionModule {
@Binds @IntoMap @ClassKey(ConcreteAction1.class)
IAction bindActionClass1(ConcreteAction1 action1);
@Binds @IntoMap @ClassKey(ConcreteAction2.class)
IAction bindActionClass2(ConcreteAction2 action2);
// ...
@Binds @IntoMap @StringKey("name_1")
IAction bindActionName1(ConcreteAction1 action1);
@Binds @IntoMap @StringKey("name_2")
IAction bindActionName2(ConcreteAction2 action2);
// ...
}
public class ActionFactory implements IActionFactory{
@Inject Map<Class<?>, Provider<IAction>> classActionFactory;
@Inject Map<String, Provider<IAction>> stringActionFactory;
@Override
public IAction createByClass(Class<?> clazz) {
// TODO: handle missing entries gracefully
return classActionFactory.get(clazz).get();
}
@Override
public IAction createByName(String name) {
return stringActionFactory.get(name).get();
}
}
在这一点上,主要的困难是你要绑定每个动作两次,每张地图一次。如果这是一个问题,您可以使用 Set 绑定来聚合一组配置,然后使用映射绑定来检索正确的 Provider。
推荐阅读
- cluster-computing - slurm集群管理器中如何知道一个job的每个进程的状态?
- javascript - 在 Camunda 进程中,如何使用 JavaScript 和 Spin 从 JSON 中检索布尔值?
- ios - 在 textViewDidChange 中检测粘贴 UITextView
- r - r data.table 使用具有多列集的 .SD 来获得 RMSPE
- javascript - 立即动态更改图像 Vanila javascript
- asp.net-core - 多租户 .Net Core Web API
- angular - 在打字稿的另一个私有方法中解析函数内私有方法调用的范围
- java - 防止 Vuejs 应用程序重写 URL
- python - 从 spyder 在 GPU 上实现 python 代码
- c# - 如何在嵌套类中编写 Xml 命名空间