【发布时间】:2015-06-01 10:22:41
【问题描述】:
几个月来,我一直在使用 MVVM 和依赖注入进行 iOS 开发,我对结果非常满意。代码非常清晰,更容易测试。但是我一直在纠结一个问题,我还没有找到让我感到非常满意的解决方案。
为了理解这个问题,我想给你一点上下文。我一直在工作的最后一个应用程序是按以下方式/层构建的:
- 型号
- 查看模型
- 视图/视图控制器
- 服务:知道如何处理 Twitter、Facebook 等外部服务的类。
- 存储库:存储库是知道如何与应用程序的 REST API 资源交互的类。假设我们有一个博客应用程序,我们可以拥有用户资源和帖子资源。这些资源中的每一个都有几种方法。资源和存储库之间存在一对一的关系。
当应用程序启动时,我们有一个 Bootstrap 类来初始化应用程序并创建主视图模型。我们有一个限制,只有视图模型可以创建其他视图模型。例如,如果有一个包含元素列表的视图(在 iOS 中,它将用 UITableView 表示)和每个元素的详细视图,这些元素通过在点击元素后将其推送到导航堆栈来呈现在列表中。我们所做的是让附加到表视图控制器的视图模型创建详细视图模型。表视图控制器监听表视图模型,然后通过创建详细视图控制器并将其视图模型传递给它来呈现详细视图模型。所以视图控制器不知道如何创建视图模型,它只知道如何为该视图模型创建视图控制器。
父视图模型是否有责任将所有依赖项传递给子视图模型。
当视图层次结构非常深入的视图模型需要其父控制器不需要的依赖项时,就会出现问题。例如访问某些外部 Web 服务的服务。因为它的父级没有该依赖项,所以必须将其添加到其依赖项列表中,从而向构造函数添加一个新参数。想象一下,如果祖父母也没有依赖关系,会发生什么情况。
您认为什么是好的解决方案?可能的解决方案:
- 单例:更难测试,它们基本上是全局状态
- 工厂类:我们可以使用一组知道如何创建特定类型对象的工厂。例如 ServiceFactory 和 RepositoryFactory。服务工厂可以具有创建服务的方法,例如:TwitterService、FacebookService、GithubService。存储库工厂可以知道如何为每个 API 资源创建存储库。在有几个工厂(2 或 3 个)的情况下,所有视图模型都可能依赖于这些工厂。
目前我们选择了工厂类解决方案,因为我们不需要使用单例,我们可以将工厂视为任何其他依赖项,这使得测试相对容易。问题是它感觉像是一个很好的对象,并且通过拥有一个工厂,您实际上并不知道哪个是需要视图模型的真正依赖项,除非您查看构造函数的实现以检查正在调用哪些工厂方法。
【问题讨论】:
-
我一直在为同样的问题苦苦挣扎,几个月来我一直在使用带有 RAC 的 MVVM,并且通常对此非常满意。但是臃肿的构造函数是一种很大的代码气味。到目前为止,我一直推迟解决这个问题,但如果我不尽快解决它,我相信它会适得其反。
标签: ios mvvm dependency-injection