实例化对象的类型取决于另一个对象的类型

时间:2014-07-14 12:39:05

标签: objective-c oop design-patterns

作为我模特的一部分,我有一个名为“幻灯片”的课程,它有两个孩子:“QuizzSlide”和“ImageSlide”。我还有另一个名为“SlideView”的类(这是我的观点的一部分),它有两个孩子“QuizzSlideView”和“ImageSlideView”。

现在我要做的是浏览幻灯片的集合并创建正确的SlideView来显示它们。问题是,要实例化SlideView,我需要知道Slide的类型。 QuizzSlide应该创建一个QuizzSlideView,而ImageSlide应该创建一个ImageSlideView。我看到两个选择:

  1. 反思。我不喜欢内省,因为它意味着构建对象的类必须详尽地列出它可以处理的对象类型。如果我在行下添加另一种类型的幻灯片,我必须修改构建器类。

  2. 使幻灯片创建其关联的视图。所以我有一个函数getView被Slide的每个子项覆盖,为该幻灯片创建正确的View。这可以工作,它会使维护更容易,但它会使程序混乱,因为模型不应包含对它所代表的视图的引用。

  3. 这就是它。我还有其他选择吗?关于如何从我的视图中解开我的模型,根据模型类型构建正确的视图并避免内省的任何想法?

    由于

2 个答案:

答案 0 :(得分:1)

我认为内省方法是最好的,但如果您担心如果引入新类(合法的问题)必须修改代码,那么我会将其设为表驱动,这将限制所需的新代码量。

(注意我还没有测试过这段代码):

static struct {
    Class slideClass;
    Class viewClass;
} _slideMap[] = {
    { [QuizzSlide class], [QuizzView class] },
    { [ImageSlide class], [ImageView class] }
};
#define NUM_SLIDE_MAPS (sizeof(_slideMap) / sizeof(_slideMap[0]))

然后使用:

for (id slide in _slides) {
    UIView *view = nil;
    CGRect frame = ...;
    for (unsigned i = 0; i < NUM_SLIDE_MAPS && !view; i++)
        if ([slide isKindofClass:_slideMap[i].slideClass])
            view = [[_slideMap[i].viewClass alloc] initWithFrame:frame];
    NSAssert(view, @"Missing slide/view map entry for class %@", NSStringFromClass([slide class]));
}        

注意:由于表达式[QuizzSlide class]不是常量表达式,因此该代码可能无法编译,在这种情况下,您将被迫使用{在运行时创建数组{1}}声明或其他一些。

您也可以使用dispatch_once()来保存幻灯片和视图类之间的映射,从而获得更快的查找性能。

答案 1 :(得分:1)

为什么createView()上的Factory method Slide QuizzSlide类在QuizzSlideView中实现时返回ImageSlide并在ImageSlideView中返回CreateIterator()指向正确的模型。

这让我想起了Iterator模式,其中{{1}}是工厂方法。

Iterator pattern in UML http://www.silversoft.net/docs/dp/hires/Pictures/itera040.gif