何为模板方法模式
模板方法模式:定义了一个操作中算法的骨架,而降一些步骤延迟到子类中。模板方法使子类可以从定义算法的某些特定步骤而不是改变算法的结构
何时使用模板方法
1.需要一次性实现算法的不变的部分,并将可变的行为留给子类来实现
2.子类的共同行为应该被提取出来放到公共类中,以避免代码重复。现有代码的差别应该被分离为新的操作,然后用一个调用这些新操作的模板方法来替代这些不同的代码
3.需要控制子类的扩展,可以定义一个在特定点调用的“钩子”操作的模板的办法。子类可以通过对钩子操作的实现在这些点扩展功能
钩子操作给出了默认行为,子类可对其扩展,默认行为通常是什么都不做。子类可以重载这个方法,为模板算法提供附加操作
模板方法模式中的控制结构流程是倒转的,因为父类的模板方法调用其子类的操作,而不是子类调用父类的操作,这与”好莱坞原则“类似:别给我们打电话,我们会打电话给你。
模板方法会调用5种类型的操作
1.对具体类或客户端类的具体操作
2.对抽象类的具体操作
3.抽象操作
4.工厂方法
5.钩子操作
模板方式与委托模式的比较
代码实现
父类:TestPaper.h
#import <Foundation/Foundation.h>
@interface TestPaper : NSObject
-(void)TestQuestion1;
-(void)TestQuestion2;
-(NSString *)Answer1;
-(NSString *)Answer2;
@end
TestPaper.m
#import "TestPaper.h"
@implementation TestPaper
-(void)TestQuestion1{
NSLog(@"问题:杨过得到,后来给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是[ ]:a.球磨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维");
NSLog(@"答案是%@",[self Answer1]);
}
-(void)TestQuestion2{
NSLog(@"问题:杨过、程英、陆无双铲除了情花,造成[ ]:a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化");
NSLog(@"答案是%@",[self Answer2]);
}
-(NSString *)Answer1{
return nil;
}
-(NSString *)Answer2{
return nil;
}
@end
子类A TestPaperA.h
#import "TestPaper.h"
@interface TestPaperA : TestPaper
@end
TestPaperA.m
#import "TestPaperA.h"
@implementation TestPaperA
-(NSString *)Answer1{
return @"b";
}
-(NSString *)Answer2{
return @"c";
}
@end
子类B TestPaperB.h
#import "TestPaper.h"
@interface TestPaperB : TestPaper
@end
TestPaperB.m
#import "TestPaperB.h"
@implementation TestPaperB
-(NSString *)Answer1{
return @"c";
}
-(NSString *)Answer2{
return @"a";
}
@end
客户端
#import <Foundation/Foundation.h>
#import "TestPaperA.h"
#import "TestPaperB.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
TestPaperA *a=[[TestPaperA alloc]init];
[a TestQuestion1];
[a TestQuestion2];
TestPaperB *b=[[TestPaperB alloc]init];
[b TestQuestion1];
[b TestQuestion2];
}
return 0;
}
结果