使用本地对象映射/解耦远程数据

时间:2013-01-14 02:34:41

标签: ios oop networking

应用程序从服务器(通常是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-to-Object映射?也许是工厂?或者我的网络管理员是否应该直接创建并将现成的对象返回给我?

也许是这样的:

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

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

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

1 个答案:

答案 0 :(得分:1)

我已经遇到过这个问题几次,并且和你有很多相同的问题。最后我认为对我有用的是:

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

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

  1. 在您的域模型中编写类方法(class)HighLevelObject>>from(aLowLevelObject)。这需要一个低级对象并自行配置。您可以为所有具有低级别对象的高级对象执行此操作。
  2. 与前一个相反:在低级对象中编写实例方法LowLevelObject>>createHighLevelObject(),创建域模型的实例。在这里,您需要将创建新对象的责任转移到下层。
  3. 创建factorybuilder(取决于模型的复杂程度),负责整个创作过程。
  4. 如果你有简单的模型,它们之间有很多1到1的映射,我会选择选项1或2.选择哪一个很大程度上取决于你的口味;选项1)的优点是对象知道如何构造自身,但将转换过程负担放在域模型中。第二种方法留下了一个“更清洁”的域模型,但迫使下层知道上层的细节,并可能迫使你打破封装。我不认为这里有一颗银弹;恕我直言,你应该选择最适合你的需求和编程品味的方法。

    HTH