Objective-c设计建议使用不同的数据源,在测试和实时之间交换

use*_*341 7 architecture iphone design-patterns objective-c

我正在设计一个应用程序,这是一个更大的工作的一部分,取决于其他人构建一个应用程序可以用来检索数据的API.

当我在考虑如何设置这个项目并围绕它设计架构时,我发生了一些事情,我相信很多人都处于类似情况.

由于我的工作取决于其他人完成他们的任务和测试服务器,这会减慢我的工作量.

所以问题是:创建测试存储库和类,实现它们的最佳实践是什么,而不必依赖于更改代码中的几个位置以在测试类和实际存储库/正确的api调用之间进行交换.

考虑以下场景:

GetDataFromApiCommand *getDataCommand = [[GetDataFromApiCommand alloc]init];
getDataCommand.delegate = self;
[getDataCommand getData];
Run Code Online (Sandbox Code Playgroud)

一旦数据通过API可用,"GetDataFromApiCommand"就可以使用实际的API,但在此之前,在调用[getDataCommand getData]时可以返回一组模拟数据.

在代码的不同位置可能存在多个这样的实例,因此无论它们在哪里都替换它们,这是一个缓慢而痛苦的过程,这不可避免地导致一两个被忽略.

在强类型语言中,我们可以使用依赖注入,只需改变一个地方.在objective-c中可以实现工厂模式,但这是最好的途径吗?

GetDataFromApiCommand *getDataCommand = [GetDataFromApiCommandFactory buildGetDataFromApiCommand];
getDataCommand.delegate = self;
[getDataCommand getData];
Run Code Online (Sandbox Code Playgroud)

达到此结果的最佳做法是什么?

由于这将是最有用的,即使您有实际的API可用,运行测试或脱机工作,ApiCommands也不一定必须永久替换,而是选择"我是否要使用TestApiCommand或ApiCommand".

更有意思的是可以选择切换:所有命令都是test,所有命令都使用实时API,而不是逐个选择它们,但这对于测试一个或两个实际API命令,混合也很有用他们有测试数据.


编辑 我选择的方式是使用工厂模式.

我按如下方式设置工厂:

@implementation ApiCommandFactory
+ (ApiCommand *)newApiCommand
{
    // return [[ApiCommand alloc]init];
    return [[ApiCommandMock alloc]init];
}
@end
Run Code Online (Sandbox Code Playgroud)

在任何我想使用ApiCommand类的地方:

GetDataFromApiCommand *getDataCommand = [ApiCommandFactory newApiCommand];
Run Code Online (Sandbox Code Playgroud)

当需要实际的API调用时,可以删除注释并注释掉mock.

在消息名称中使用new表示谁曾使用工厂获取对象,负责释放它(因为我们想避免在iPhone上自动释放).

如果需要其他参数,工厂需要考虑这些因素,即:

[ApiCommandFactory newSecondApiCommand:@"param1"];
Run Code Online (Sandbox Code Playgroud)

这对于存储库也很有效.

Jer*_*myP 1

在消息名称中使用 new 意味着谁使用工厂来获取对象,谁就负责释放它(因为我们希望避免 iPhone 上的自动释放)。

您不必执着于不自动释放。它实际上仅适用于您碰巧在事件循环的一次迭代中创建大量自动释放对象的情况。如果该对象的寿命足够长,否则您将在工厂方法之外保留它,那么返回一个自动释放的对象将只花费您在自动释放池中的一个引用。

不管怎样,回答你的问题,你的选择几乎正是我会做的。还可以考虑创建一个与 API 匹配的 Objective-C 协议,并且您的 APICommandMock 和 APICommand 必须符合该协议。这将记录 API 并为您和其他团队提供一些纪律。例如,它将确定方法名称和参数类型等内容。