这里谈谈策略和模板方法模式,之所以把这两个模式放在一起,是因为从结构上来讲他们很像。
先来说策略模式,它实现起来很其实简单,它和模板方法在结构上的主要差异在于抽象对象采用抽象类还是协议。
这个抽象对象当中的方法相当于java/C#里的virtual方法,甚至如果有需要可以弄成abstract方法。
但是OC当中并没有这两个概念,其实这样设计是有好处的,由于这种不严格性,就没有必要考虑接口变动时的版本兼容性问题。
下面来模仿一个抽象类。
以一个正则校验逻辑为例子:
抽象策略:
1 #import <Foundation/Foundation.h> 2 3 @interface ValidateStrategy : NSObject 4 -(BOOL)validate:(NSString *)str; 5 @end
1 #import "ValidateStrategy.h" 2 3 @implementation ValidateStrategy 4 -(BOOL)validate:(NSString *)str { 5 return NO; 6 } 7 @end
具体策略之一:
1 #import <UIKit/UIKit.h> 2 #import "ValidateStrategy.h" 3 @interface NumberValidateStrategy : ValidateStrategy 4 -(BOOL)validate:(NSString *)str; 5 @end
1 @implementation NumberValidateStrategy 2 -(BOOL)validate:(NSString *)str{ 3 NSError *regError = nil; 4 NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^\d+$" options:NSRegularExpressionAnchorsMatchLines error:®Error]; 5 NSUInteger numberOfMatches = [regex numberOfMatchesInString:str options:NSMatchingAnchored range:NSMakeRange(0, [str length])]; 6 return (regError == nil && numberOfMatches != 0); 7 } 8 @end
调用端:
1 - (IBAction)checkNumberBtn:(UIButton *)sender { 2 ValidateStrategy *strategy = [[NumberValidateStrategy alloc]init]; 3 4 BOOL validateResult = [strategy validate:[self.inputText text]]; 5 NSLog(@"%d", validateResult); 6 }
整体思路和在java/C#当中是一样的,具体的策略类的获取也通过依赖注入的方式获得,这里不再赘述。
接下来说模板方法模式,它的结构和和策略模式很类似,我觉得没必要用太多的代码来描述它。
差别只是在抽象类当中定义了一个调用入口,其中包含对方法调用的骨架,然后由子类来重写这些方法。
唯一一个需要解决的问题是,如何保证一个子类”必须“重载这个方法。
在java/C#当中,骨架方法通常是虚方法,如果必须重载,则是抽象方法,在上面已经提到了,OC可以达到虚方法的效果,
但是OC没有抽象方法机制,所以可以在父类的方法当中抛异常来达到同样的目的:
1 -(void)mustOverrideMethod { 2 [NSException raise:NSInternalInconsistencyException format:@"您必须重载该方法"]; 3 }