Objective-c中的AbstractFactory模式

时间:2012-08-27 13:10:27

标签: objective-c abstract-factory

我只是想学习目标-c。

我已经在不同语言中看到了AbstractFactory模式的维基百科示例。

这里是按钮定义:

@protocol Button
- (void)paint;
@end

@interface WinButton : NSObject <Button>
@end

这是一家工厂:

@implementation WinFactory
- (id)createButton {
    return [[[WinButton alloc] init] autorelease];
}
@end

就我而言,obj-c的id关键字应该类似于C#&#39; var或C ++ 11&{39} auto , 正确?

所以我的问题是:

为什么让工厂返回未指定类型的通用对象? 这是一个错误(让工厂返回其他非Button的东西)还是有任何理由这样做?

我以这种方式写工厂:

@implementation WinFactory
- (id<Button>)createButton {
    return [[[WinButton alloc] init] autorelease];
}
@end 
我错了吗?

3 个答案:

答案 0 :(得分:6)

  

为什么让工厂返回未指定类型的通用对象?

在许多情况下,您看到id返回,这是因为它们不是一致的类型(真正的抽象对象),或者是因为会引入隐式的向上转换。

  

这是一个错误(让工厂返回其他非Button的东西)还是有任何理由这样做?

这不是错误。当然,你不应该返回一个不匹配的类型。

  

我会这样写一个工厂:......我错了吗?

@implementation WinFactory
- (id<Button>)createButton {
    return [[[WinButton alloc] init] autorelease];
}
@end

这种情况下的最大问题是ObjC的输入类型非常松散,您应该努力确保所有选择器的参数和返回类型匹配。也就是说,所有翻译中的每个createButton都应该返回相同的类型并且具有相同的参数类型。有时您必须选择更具描述性的名称,以避免编译器的歧义。

这应该解释为什么+[NSString string]会返回id - 如果它返回NSString,那么+[NSMutableString string]可能会成为警告的来源。这是因为编译器可能具有将方法声明与动态实例匹配的困难(不可能)时间。这也可以帮助您理解选择器的'罗嗦'命名,例如方便构造函数,它也包含方法中的类型(例如+[NSDictionary dictionaryWithObject:]而不是简单的+[NSDictionary withObject:])。

但是要回答你的问题:id<Button>NSObject<Button>*或其他一些合格的类型就好了 - 只要您可以使用该常用方法签名。您正在引入类型限定,这有助于编译器帮助

答案 1 :(得分:4)

这里更正确的返回类型是:

- (id<Button>)createButton;

这意味着返回的类型是符合<Button>协议的对象。我可以修改WP页面,以便更清楚一些。 <Button>协议还应继承<NSObject>协议以保证完整性(并简化实际使用)。

请注意,ObjC中的抽象工厂模式有点不寻常。我试图想一下它在UIKit或Foundation中使用的情况。类在内部处理(例如在NSNumber中)并且被称为类集群更常见。

要小心尝试在ObjC中使用C ++或C#样式进行编码。 ObjC不是静态语言,使用的模式通常是完全不同的。 (我不是说AF是一种静态模式。它可以在ObjC中使用得很好。我只是说你在尝试学习ObjC时看着它的事实意味着你可能会向后接近它,学习“我如何在ObjC中做这个C ++”,而不是学习“我如何在ObjC中开发。”)

答案 2 :(得分:0)

Objective-C具有类集群的概念,它是抽象工厂。 See this answer.