我想到了几个想法。取决于您想要交换的方式和时间。一种可能性是使用配置实例化您的模块。可以是一个简单的布尔值:
@Module
public class RepositoryModule {
private final boolean isDemo;
public RepositoryModule(boolean isDemo) {
this.isDemo = isDemo;
}
@Provides
public Repository providesRepository() {
return isDemo? new DemoRepository() : new RemoteRepository();
}
// Other providers
}
我不喜欢这种方法,但它适合您的用例。我相信这是相当严格的,并且不允许易于维护。我可能会选择使用工厂并提供工厂而不是仓库本身。
public interface RepositoryFactory {
Repository getRepository(Configuration configuration);
}
public class RepositoryFactoryImpl implements RepositoryFactory {
@Inject
public RepositoryFactoryImpl() {}
// The implementation
}
@Module
public class RepositoryModule {
@Provides
public RepositoryFactory providesRepositoryFactory(
RepositoryFactoryImpl factory) {
return factory;
}
// Other providers
}
Configuration 将是一个简单的 POJO,您可以在其中指定多个属性来配置您的存储库。比如说:
public class Configuration {
private final boolean isDemo;
// all the POJO stuff you need
}
然后您可以使您的域对象依赖于工厂:
public class SomeAwesomeBusinessLogic {
private final RepositoryFactory repositoryFactory;
@Inject
public SomeAwesomeBusinessLogic(
RepositoryFactory repositoryFactory) {
this.repositoryFactory = repositoryFactory;
}
//awesome stuff going down
}
然后您可以在业务逻辑中执行repositoryFactory.getRepository(new Configuration(true/false));。
我更喜欢这种方法,因为它更容易扩展到新类型的存储库。您还可以测试工厂逻辑是否正确。通常没有人测试 dagger 模块,这就是为什么我不太热衷于第一种方法。
另一个好处是,如果有可能更改应用程序的配置并突然更改为演示存储库,这种方法允许您保留相同的模块实例,方法是向工厂提供不同的 Configuration 对象。
第三种可能是Producers。但是,这实际上取决于您的用例以及您希望如何处理此运行时依赖项交换。我觉得这种方法很好,但可能有点矫枉过正。
希望对你有帮助