Objective c 实例化一个对象';s类型取决于另一个对象';s型
作为我模型的一部分,我有一个名为“幻灯片”的班级,它有两个孩子:“测验幻灯片”和“图像幻灯片”。我还有另一个叫做“SlideView”的类(这是我观点的一部分),它有两个孩子“QuizzSlideView”和“ImageSlideView” 现在我要做的是浏览一组幻灯片,并创建正确的幻灯片视图来显示它们。问题是,要实例化SlideView,我需要知道幻灯片的类型。QuizzSlide应创建QuizzSlideView,ImageSlide应创建ImageSlideView。我看到两种选择:Objective c 实例化一个对象';s类型取决于另一个对象';s型,objective-c,oop,design-patterns,Objective C,Oop,Design Patterns,作为我模型的一部分,我有一个名为“幻灯片”的班级,它有两个孩子:“测验幻灯片”和“图像幻灯片”。我还有另一个叫做“SlideView”的类(这是我观点的一部分),它有两个孩子“QuizzSlideView”和“ImageSlideView” 现在我要做的是浏览一组幻灯片,并创建正确的幻灯片视图来显示它们。问题是,要实例化SlideView,我需要知道幻灯片的类型。QuizzSlide应创建QuizzSlideView,ImageSlide应创建ImageSlideView。我看到两种选择: 内省
谢谢我认为内省方法是最好的,但是如果您担心在引入新类时必须修改代码(这是一个合理的考虑),那么我会将其设置为表驱动,这将限制所需的新代码量 (注意,我没有测试此代码): 然后使用:
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]));
}
for(id幻灯片中的幻灯片){
UIView*view=nil;
CGRect帧=。。。;
对于(无符号i=0;i
注意:此代码可能无法编译,因为表达式[QuizzSlide class]
不是常量表达式,在这种情况下,您将被迫在运行时使用dispatch\u once()
语句或类似语句创建数组
您还可以使用NSDictionary
来保存幻灯片类和视图类之间的映射,并获得更快的查找性能。为什么不在幻灯片
类中使用createView(),当在QuizzSlide
中实现时,返回一个QuizzSlideView
并在ImageSlide
中返回一个指向正确模型的ImageSlideView
这让我想起了模式,CreateIterator()
是工厂方法
我不明白这一复杂情况(也许我遗漏了什么)。在控制器中,如果([slideInstance isKindOfClass:[QuizzSlide class]]){view=[[QuizzView alloc]initWithFrame…];}如果(…){…}
,如果我想使用内省,这不是一个的例子吗?是的。但这意味着,对于我稍后添加的每种幻灯片类型,我都必须返回到该控制器并添加另一个“isKindOfClass”,此外,我想对这些幻灯片类集体执行的任何操作都需要一个“isKindOfClass”。我想避免那样,谢谢。这是内省问题的合理解决方案,我可能会同意。我在研究解决方案时偶然发现了访问者模式,但我仍在尝试它是否以优雅的方式解决了我的问题。是的,这是我提到的第二个选择,这个解决方案的唯一问题是我将模型与我的视图绑定在一起。这通常是不好的,但在我的例子中尤其糟糕,因为模型和视图有不同的生命周期。等等,除非你是说幻灯片应该只创建对象而不保存引用?六羟甲基三聚氰胺六甲醚。。。这可能真的有用!我试试看。谢谢。为什么模型元素不知道他们的观点?这是因为假设视图相对于其模型不太稳定,并且您希望避免不必要地将更改传播到模型中。你提到的“可怕的混乱”。如果您认为视图变化太大,可以在实例化视图时将视图插入幻灯片中。但这似乎又是一场混乱,就像自省。每张幻灯片一个视图的关系可能是稳定的,很像迭代器示例。您可以选择您的战斗(混乱),并接受模型了解其视图的风险。
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]));
}