策略模式是一種常見的軟件設計模式,這里簡單得介紹一下策略模式并用IOS簡單實現一下。
所謂的策略模式,顧名思義是要采用不同的策略的。一般來說,在不同的情況下,處理某一個問題的方法也不一樣。比如說對字符串的排序和對數字的排序,雖然用的都是快排,但是顯然不可能使用一段通用的代碼。有人說java里面的compareTo可以做到,但如果考慮這么一個問題:同樣是出門旅行,老年人身體虛弱,需要大量的休息,而孩子則是精力充沛,希望玩到更多的景點。如何在同一模式下表達以上信息、采用合理的設計模式進行封裝而不是大量重寫類似的代碼,就需要學習并采用策略模式。
例子
該例子主要利用策略模式來判斷UITextField是否滿足輸入要求,比如輸入的只能是數字,如果只是數字就沒有提示,如果有其他字符則提示出錯。驗證字母也是一樣。
首先,我們先定義一個抽象的策略類IputValidator。代碼如下:
InputValidator.h
static NSString * const InputValidationErrorDomain = @"InputValidationErrorDomain";
@interface InputValidator : NSObject
//實際驗證策略的存根方法
-(BOOL)validateInput:(UITextField *)input error:(NSError **)error;
@end
#import "InputValidator.h"
@implementation InputValidator
-(BOOL)validateInput:(UITextField *)input error:(NSError **)error
{
if (error) {
*error = nil;
}
return NO;
}
@end
#import "InputValidator.h"
@interface NumericInputValidator : InputValidator
-(BOOL)validateInput:(UITextField *)input error:(NSError **)error;
@end
@implementation NumericInputValidator
-(BOOL)validateInput:(UITextField *)input error:(NSError **)error
{
NSError *regError = nil;
//使用配置的NSRegularExpression對象,檢查文本框中數值型的匹配次數。
//^[0-9]*$:意思是從行的開頭(表示為^)到結尾(表示為$)應該有數字集(標示為[0-9])中的0或者更多個字符(表示為*)
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^[0-9]*$" options:NSRegularExpressionAnchorsMatchLines error:®Error];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:[input text] options:NSMatchingAnchored range:NSMakeRange(0, [[input text] length])];
//如果沒有匹配,就返回錯誤和NO
if (numberOfMatches==0) {
if (error != nil) {
NSString *description = NSLocalizedString(@"Input Validation Faild", @"");
NSString *reason = NSLocalizedString(@"The input can contain only numerical values", @"");
NSArray *objArray = [NSArray arrayWithObjects:description,reason, nil];
NSArray *keyArray = [NSArray arrayWithObjects:NSLocalizedDescriptionKey,NSLocalizedFailureReasonErrorKey ,nil];
NSDictionary *userInfo = [NSDictionary dictionaryWithObjects:objArray forKeys:keyArray];
*error = [NSError errorWithDomain:InputValidationErrorDomain code:1001 userInfo:userInfo];
}
return NO;
}
return YES;
}
@end
@interface AlphaInputValidator : InputValidator
- (BOOL)validateInput:(UITextField *)input error:(NSError **)error;
@end
-(BOOL)validateInput:(UITextField *)input error:(NSError **)error
{
NSError *regError = nil;
//使用配置的NSRegularExpression對象,檢查文本框中數值型的匹配次數。
//^[0-9]*$:意思是從行的開頭(表示為^)到結尾(表示為$)應該有數字集(標示為[0-9])中的0或者更多個字符(表示為*)
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^[a-zA-Z]*$" options:NSRegularExpressionAnchorsMatchLines error:®Error];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:[input text] options:NSMatchingAnchored range:NSMakeRange(0, [[input text] length])];
//如果沒有匹配,就返回錯誤和NO
if (numberOfMatches==0) {
if (error != nil) {
NSString *description = NSLocalizedString(@"Input Validation Faild", @"");
NSString *reason = NSLocalizedString(@"The input can contain only letters ", @"");
NSArray *objArray = [NSArray arrayWithObjects:description,reason, nil];
NSArray *keyArray = [NSArray arrayWithObjects:NSLocalizedDescriptionKey,NSLocalizedFailureReasonErrorKey ,nil];
NSDictionary *userInfo = [NSDictionary dictionaryWithObjects:objArray forKeys:keyArray];
*error = [NSError errorWithDomain:InputValidationErrorDomain code:1002 userInfo:userInfo];
}
return NO;
}
return YES;
}
@end
@property(nonatomic,strong)InputValidator *inputValidator;
-(BOOL)validate;
@end
#import "CustomTextField.h"
#import "InputValidator.h"
@implementation CustomTextField
-(BOOL)validate {
NSError *error = nil;
BOOL validationResult = [_inputValidator validateInput:self error:&error];
if (!validationResult) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[error localizedDescription] message:[error localizedFailureReason] delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", @"") otherButtonTitles: nil];
[alertView show];
}
return validationResult;
}
@end
@end
- (void)viewDidLoad {
[super viewDidLoad];
_numberTextField.inputValidator = [NumericInputValidator new];
_letterTextField.inputValidator = [AlphaInputValidator new];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - ValidButtonMehtod
- (IBAction)validNumAction:(id)sender {
[_numberTextField validate];
}
- (IBAction)validLetterAction:(id)sender {
[_letterTextField validate];
}
@end
優點
使用場景
總結
再總結一下策略方法的實現,本質上就是需要完成一個事情(出行),但是并不清楚需要使用怎樣的策略,所以封裝出一個函數,能夠把需要的策略(young OR old)作為參數傳遞進來,并且使用相應的策略完成這個事件的處理。
最后簡單談一談個人對于策略模式和面向對象中多態的思想的理解,首先多態是高層次,高度抽象的概念,獨立于語言之外,是面向對象思想的精髓,而策略模式只是一種軟件設計模式,相對而言更加具體,而且具體實現依賴于具體的編程語言,比如OC和java的實現方法并不相同,是language-dependent的。其次,多態更多強調的是,不同的對象調用同一個方法會得到不同的結果,而策略模式更多強調的是,同一個對象(事實上這個對象本身并不重要)在不同情況下執行不同的方法,而他們的實現方式又是高度類似的,即共享同一個父類并且各自重寫父類的方法。
以上觀點純屬個人愚見,歡迎大牛指正,互相交流。
新聞熱點
疑難解答