我已经使用MVVM和依赖注入进行iOS开发几个月了,我对结果感到非常满意。代码更加清晰易懂,也更容易测试。但是我一直在解决一个问题,但还没有找到让我非常满意的解决方案。
为了理解这个问题,我想给你一些背景。我最近正在工作的应用程序的架构如下所示/层:
- 模型
- 视图模型
- 视图/视图控制器
- 服务:知道如何处理外部服务(如Twitter,Facebook等)的类。
- 存储库:Repository是一个类,知道如何与应用程序的REST API资源交互。假设我们有一个博客应用程序,我们可以拥有用户资源和帖子资源。每个资源都有几种方法。资源与存储库之间存在1对1的关系。
当应用程序启动时,我们有一个引导类,它初始化应用程序并创建主视图模型。我们有一个限制,只有视图模型才能创建其他视图模型。例如,在具有元素列表的视图中(在iOS中,它将表示为UITableView),以及在单击列表中的元素后推送到导航堆栈中呈现每个元素的详细信息视图。我们所做的是使附加到表视图控制器的视图模型创建详细视图模型。表视图控制器侦听表视图模型,然后通过创建详细视图控制器并将其视图模型传递给它来呈现详细视图模型。因此,视图控制器不知道如何创建视图模型,它只知道如何为该视图模型创建视图控制器。
父视图模型有责任将所有依赖项传递给子视图模型。
问题出在一个非常深的视图模型需要其父控制器不需要的依赖项,例如访问某些外部Web服务的服务。因为它的父级没有这个依赖性,所以它将不得不将其添加到其依赖项列表中,从而向构造函数添加一个新参数。如果祖先也没有该依赖项,想象一下这将如何进行。你认为什么是好的解决方案?可能的解决方案:
- 单例:更难测试,基本上是全局状态。 - 工厂类:我们可以创建一组知道如何创建某些对象类型的工厂。例如ServiceFactory和RepositoryFactory。Service factory可以有用于创建服务的方法,例如TwitterService、FacebookService和GithubService。存储库工厂可以知道如何为每个API资源创建存储库。如果只有几个工厂(2或3),则所有视图模型都可以依赖于这些工厂。
目前,我们选择了工厂类解决方案,因为我们不需要使用单例,并且我们可以将工厂视为任何其他依赖关系,这使得它相对容易测试。问题在于它感觉像一个好的对象,通过拥有一个工厂,你实际上不知道哪个是需要视图模型的真正依赖性,除非你查看构造函数的实现以检查调用了哪些工厂方法。