在前面的例子中,我们吐槽了在默认情况下,Dagger 生成的代码会有一些方法名不怎么好看,例如上面的 cPUProvider
、uPSExpress
这种。那么有人就说了,这个地方能不能改得更好看一点呢?答案肯定是可以的。
这就要介绍 @Component
注解中的另外两个注解了: @Component.Builder
和 @Subcomponent.Factory
。通过这两个注解,我们可以对 Dagger 生成 Component
的实现类有一定的控制。
当我们创建一个类时,常用的设计模式就是 Builder 构造器模式和 Factory 工厂模式,其实这两个就对应了上述的两个注解。这里我们一个一个说,先说更为常用的 @Component.Builder
,然后再介绍 @Subcomponent.Factory
。
@Component.Builder
在我们不往 Component
接口中添加 Builder
或 Factory
时,Dagger 模式使用的就是这种构造器模式,但是咱们仍然可以使用这个注解,对生成代码的过程进行一些控制。
这里我们就修改一下 ZTOExpress
这个类,为其添加一个 Builder
:
@SanScope
@Component(modules = {TaoBao.class}, dependencies = UPSExpress.class)
public interface ZTOExpress {
void deliverTo(Person person);
ZTOShanghaiExpress.Factory getShanghaiDepartmentFactory();
@Component.Builder
interface Builder {
Builder setTaoBao(TaoBao taoBao);
Builder setUPSExpress(UPSExpress upsExpress);
ZTOExpress build();
}
}
很简单,在 ZTOExpress
中再添加一个 Builder
并使用 @Component.Builder
标注,而 Builder
里面的内容,就是很普通的构造器模式,咱们可以在里面修改代码。
在添加了这段代码后,只需要调用我们自己定义的 set
方法构造 ZTOExpress
然后再使用就行。这里就不演示了。
@Component.Factory
除了使用 Builder
模式,Dagger 还支持 Factory
工厂模式,其使用方式也跟上面的 Builder
类似。但是有一点需要注意的是,同一个 Component
是不能即添加 Builder
也添加 Factory 的。
由于上面已经给 ZTOExpress
添加了 Builder
,那我们现在就给 UPSExpress
添加 Factory
注解:
@Component(modules = CPUProvider.class)
public interface UPSExpress {
@Named("AMD") CPU getAMDCPU();
@Named("Intel") CPU getIntelCPU();
@Component.Factory
interface Factory {
UPSExpress create(CPUProvider cpuProvider);
}
}
在使用了工厂模式之后,我们再构造 UPSExpress
就得用如下的方式:
UPSExpress upsExpress = DaggerUPSExpress.factory().create(new CPUProvider());
@Subcomponent.Builder 和 @Subcomponent.Factory
不仅仅是依赖注入器可以添加构造器模式或工厂模式,子组件也可以使用构造器模式或工厂模式。只不是使用的是 @Subcomponent.Builder
和 @Subcomponent.Factory
。
例如,我们给中通的上海分部添加一个 Factory
:
@Subcomponent
public interface ZTOShanghaiExpress {
void deliverTo(Person person);
@Subcomponent.Factory
interface Factory {
ZTOShanghaiExpress create();
}
}
在使用时,由于子组件是要放到主组件中的,在这么写之后,就需要修改获取子组件的方式:
ZTOShanghaiExpress.Factory getShanghaiDepartmentFactory();
如果是添加了 @Subcomponent.Builder,那就改成下面的这样:
ZTOShanghaiExpress.Builder getShanghaiDepartmentFactory();