这是模板方法模式,Java和C++可以很容易地用虚函数实现它。对象 C 如何实现这种模式?可可触摸(iOS)中的任何示例?
3 回答
正如jer已经指出的,所有 Objective-C 方法本质上都是虚拟的。这是该语言的一个特性,与其他类 C 语言不太吻合。话虽如此,模板方法模式的基础仍然可以在 Objective-C 中实现,通过“手动”强制子类实现某些功能。例如(使用链接的维基百科文章中的约定):
@interface Game
{
int playersCount;
}
- (void)playOneGame:(int)numPlayers;
// "virtual" methods:
- (void)initializeGame;
- (void)makePlay:(int)player;
- (BOOL)endOfGame;
- (void)printWinner;
@end
@implementation Game
- (void)initializeGame { NSAssert(FALSE); }
- (void)makePlay:(int player) { NSAssert(FALSE); }
- (BOOL)endOfGame { NSAssert(FALSE); return 0; }
- (void)printWinner { NSAssert(FALSE); }
- (void)playOneGame:(int)numPlayers
{
//..
}
@end
Game
上面的代码通过在调用基类实现之一时抛出异常来强制子类覆盖“虚拟”方法。实际上,这会将测试从编译器阶段(就像在 C++ 或 Java 中一样)转移到运行时阶段(在 Objective-C 中经常会做类似的事情)。
如果您真的想强制执行不允许子类覆盖该playOneGame:
方法的规则,您可以尝试(*)从init
方法中验证正确的实现:
@implementation Game
...
- (void)init
{
if ((self = [super init]) == nil) { return nil; }
IMP my_imp = [Game instanceMethodForSelector:@selector(playOneGame:)];
IMP imp = [[self class] instanceMethodForSelector:@selector(playOneGame:)];
NSAssert(imp == my_imp);
return self;
}
...
@end
(*) 请注意,此代码不会对重新实现的子类产生 100% 的坚如磐石的防御playOneGame:
,因为 Objective-C 的本质是允许子类覆盖instanceMethodForSelector:
以产生正确的结果。
在 Objective-C 中,所有方法都类似于 C++virtual
方法。
在 Objective-C 模板方法模式中,当你有一个算法的骨架但它可以以不同的方式实现时使用。模板方法定义了执行算法的步骤,它可以提供可能对所有或部分子类通用的默认实现。
让我们举个例子,但首先看图片
@interface Worker : NSObject
- (void) doDailyRoutine;
- (void) doWork; // Abstract
- (void) comeBackHome;
- (void) getsomeSleep;
@end
@implementation Worker
- (void) doDailyRoutine {
[self doWork];
[self comeBackHome];
[self getsomeSleep];
}
- (void) doWork { [self doesNotRecognizeSelector:_cmd]; }
- (void) comeBackHome { [self doesNotRecognizeSelector:_cmd]; }
- (void) getsomeSleep { [self doesNotRecognizeSelector:_cmd]; }
// [self doesNotRecognizeSelector:_cmd] it will force to call the subclass Implementation
@end
@interface Plumber : Worker
@end
@implementation Plumber
- (void) doWork { NSLog(@“Plumber Work"); }
@end
@interface Electrician : Worker
@end
@implementation Electrician
- (void) doWork { NSLog(@“Electrician Work"); }
@end
@interface Cleaner : Worker
@end
@implementation Cleaner
- (void) doWork { NSLog(@“Cleaner Work"); }
@end
在这个例子中,dowork() 是一个抽象函数,应该由所有子类实现,这种模式主要用于 Cocoa 框架中。
希望它能帮助您理解“模板方法模式”。