3

这是模板方法模式,Java和C++可以很容易地用虚函数实现它。对象 C 如何实现这种模式?可可触摸(iOS)中的任何示例?

4

3 回答 3

4

正如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:以产生正确的结果。

于 2010-12-29T04:14:09.123 回答
0

在 Objective-C 中,所有方法都类似于 C++virtual方法。

于 2010-12-29T03:02:23.183 回答
0

在 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 框架中。

希望它能帮助您理解“模板方法模式”。

于 2015-07-29T11:12:54.187 回答