我正在寻找一种方法将配置输入传递给从基类派生的工厂,并根据该工厂的派生类保存不同的输入参数。
我正在努力寻找实现这一点的好方法。因此,让我展示一下我目前的情况以及问题出在哪里:
class ExampleFragmentFactoryImpl @Inject constructor(
private val providers: List<ExampleFragmentProvider<out ExampleInput>>
): ExampleFragmentFactory {
@Suppress("UNCHECKED_CAST")
override suspend fun <T: ExampleInput> create(
pageType: T
): Fragment {
providers.forEach { provider ->
try {
val typesafeProvider = provider as? ExampleFragmentProvider<T>
typesafeProvider?.let {
return it.provide(pageType)
}
} catch (e: ClassCastException) {
// This try-except-block shall be avoided.
}
}
throw IllegalStateException("could not create Fragment for pageType=$pageType")
}
}
这里是工厂界面...
interface ExampleFragmentFactory {
suspend fun <T : ExampleInput> create(
pageType: T
): Fragment
}
现在提供者界面...
interface ExampleFragmentProvider<T: ExampleInput> {
suspend fun provide(
pageType: T
) : Fragment
}
输入类...
sealed class ExampleInput {
object NotFound : ExampleInput()
object WebView : ExampleInput()
data class Homepage(
val pageId: String
) : ExampleInput()
}
最后是提供者实现:
internal class ExampleHomepageProvider @Inject constructor() :
ExampleFragmentProvider<ExampleInput.Homepage> {
override suspend fun provide(pageType: ExampleInput.Homepage): Fragment {
TODO()
}
}
如上所述,在工厂中需要 try-except 真的很糟糕。应该有很好的方法来实现这一点而无需尝试除外。不幸的是,由于类型擦除,无法在转换之前检查类型。使用多态代码无法使用具体类型 afaik。
另一种可能的解决方案是避免在提供程序provide()
方法中使用泛型并强制转换为所需的输入类型——但这也不是很好。
你对我如何改进这种工厂有什么建议吗?