2

应用程序从服务器提取数据(通常是 JSON 字符串)是相当常见的场景。然后将这些数据解析并转换为原生类,如 NSString、NSArray、NSDictionary 等。

然而,大多数时候,我们希望使用自定义模型来表示这些远程数据。

例如,如果我们要提取一个 JSON 数组的博客文章,我们希望将它们映射到 BlogPost 模型对象中,例如:

// BlogPost.h
@interface BlogPost: NSObject
@property NSString *title;
@property NSString *body;
@property NSDate *dateCreated;
@property NSArray *comments;
@end

您将“JSON”模型与本机模型解耦的方法是什么?

我经常发现自己在模型本身中编写了一个自定义初始化程序,它接受一个字典(通常来自 JSON 提要)。

例如:

// BlogPost.h
+ (BlogPost *)blogPostWithJSON:(NSDictionary *)jsonDictionary;

然后我必须跟踪服务器上使用的密钥并将它们映射到我的属性。

这样做我总是觉得有点不安,因为应用程序中的模型不应该真的知道服务器上使用了哪些密钥。

我应该将这个 JSON 到对象的映射移到另一个类中吗?也许是工厂?或者我的网络管理员应该直接创建现成的对象并将其返回给我吗?

也许是这样的:

// NetworkManager.h
- (void)getBlogPostWithCompletion:(void (^)(BlogPost *blogPost))completionBlock;

(当然,我在这里省略了很多细节,比如要获取哪篇博文,但这只是为了展示一种方法)。

还有其他方法吗?如何将服务器数据与本地模型分离?

4

1 回答 1

1

我已经多次遇到这个问题,并且得到了与您几乎相同的问题。最后,我发现对我有用的是:

  • 创建原始模型的 OO 表示。在您的情况下,这意味着将 JSON 数组解码为它用作底层模型(字典?)的任何内容。根据您使用的服务的建模方式,您最终可能会得到一些“记录类”(即没有行为的类)。我通常更喜欢使用这些类型的类而不是数组或字典,因为随着软件的发展,这允许在需要时向它们添加行为。另一方面,如果您使用数组或字典,则不能这样做。
  • 一旦你有了一个低级的 OO 模型,就可以创建一个 OO 域模型。在这个新模型中,您可以根据您的领域需要设计事物,而不是依赖于服务提供商的模型。很多时候,您会发现您的域类和提供者的类之间存在一对一的映射,但这不是强制性的。这里的重点是您应该抽象您的领域并按照您认为正确的方式进行设计。

这两个模型之间的映射可以根据其复杂性以不同的方式完成。我通常喜欢选择这三种方法中的一种并坚持下去,以便在项目中采用同质的方法:

  1. (class)HighLevelObject>>from(aLowLevelObject)在你的领域模型中编写一个类方法。这需要一个低级对象并自行配置。您对所有具有低级对应物的高级对象执行此操作。
  2. 与前一个相反:LowLevelObject>>createHighLevelObject()在创建域模型实例的低级对象中编写一个实例方法。在这里,您将创建新对象的责任转移到较低层。
  3. 创建一个负责整个创建过程的工厂构建器(取决于模型的复杂性)。

如果您有简单的模型,它们之间有许多 1 对 1 映射,我会选择选项 1 或 2。选择哪一个很大程度上取决于您的口味;选项 1) 的优点是对象知道如何构建自己,但将转换过程的负担放在域模型中。第二种方法留下了一个“更干净”的域模型,但会迫使下层了解上层的细节,并且可能会迫使您打破封装。我不认为这里有灵丹妙药;恕我直言,您应该选择最适合您的需求和编程品味的方法。

高温高压

于 2013-01-14T16:29:10.027 回答