1.定義
策略模式定義了算法族,分別封裝起來,讓它們之間可以互相替換,此模式讓算法的變法獨(dú)立于使用算法的客戶。 —《Head First 設(shè)計(jì)模式》
2.UML圖

Context類可以理解成是業(yè)務(wù)場景,其包含了一個(gè)strategy屬性,類型是Strategy,還有一個(gè)contextInterface的方法,用于執(zhí)行Straetegy中的algrithmInterface方法(多態(tài))。
Strategy是一個(gè)抽象基類,其中包含了一個(gè)algorithmInterface的抽象方法。
StrategyA、StrategyB、StrategyC類是繼承自Strategy的具體算法類,algrithmInterface實(shí)現(xiàn)了具體的algrithmInterface方法。
3.使用
InputTextFieldValidate抽象算法類即Strategy
#import <UIKit/UIKit.h>
@interface InputTextFieldValidate : NSObject
// 策略輸入 YES 表示測試通過.No 表示測試不通過
- (BOOL)validateInputTextField:(UITextField *)textField;
@property (nonatomic, copy) NSString *attributeInputStr; /**< 屬性字符串 */
@end
#import "InputTextFieldValidate.h"
@implementation InputTextFieldValidate
- (BOOL)validateInputTextField:(UITextField *)textField {
return NO;
}
@end
LatterTextFieldValidate具體的算法類即StrategyA
#import "InputTextFieldValidate.h"
@interface LatterTextFieldValidate : InputTextFieldValidate
@end
#import "LatterTextFieldValidate.h"
@implementation LatterTextFieldValidate
- (BOOL)validateInputTextField:(UITextField *)textField {
if (textField.text.length == 0) {
self.attributeInputStr = @"字母不能是空的";
return nil;
}
// ^[a-zA-Z]*$ 從開頭(^)到結(jié)尾($), 有效字符集([a-zA-Z])或者更多(*)個(gè)字符
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^[a-zA-Z]*$" options:NSRegularExpressionAnchorsMatchLines error:nil];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:[textField text] options:NSMatchingAnchored range:NSMakeRange(0, [[textField text] length])];
// 進(jìn)行判斷,匹配不符合表示0的話, 就走下面的邏輯
if (numberOfMatches == 0) {
self.attributeInputStr = @"不全是字母, 輸入有誤,請重新輸入";
} else {
self.attributeInputStr = @"輸入正取,全部是字母";
}
return self.attributeInputStr == nil ? YES : NO;
}
NumberTextFieldValidate集體的算法類,同上
#import "InputTextFieldValidate.h"
@interface NumberTextFieldValidate : InputTextFieldValidate
@end
#import "NumberTextFieldValidate.h"
@implementation NumberTextFieldValidate
- (BOOL)validateInputTextField:(UITextField *)textField {
if (textField.text.length == 0) {
self.attributeInputStr = @"數(shù)值不能是空的";
return nil;
}
// ^[a-zA-Z]*$ 從開頭(^)到結(jié)尾($), 有效字符集([a-zA-Z])或者更多(*)個(gè)字符
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^[0-9]*$" options:NSRegularExpressionAnchorsMatchLines error:nil];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:[textField text] options:NSMatchingAnchored range:NSMakeRange(0, [[textField text] length])];
// 進(jìn)行判斷,匹配不符合表示0的話, 就走下面的邏輯
if (numberOfMatches == 0) {
self.attributeInputStr = @"不全是數(shù)字, 輸入有誤,請重新輸入";
} else {
self.attributeInputStr = @"輸入數(shù)字,全部是字母";
}
return self.attributeInputStr == nil ? YES : NO;
}
@end
CustomTextField即Context類
#import <UIKit/UIKit.h>
#import "InputTextFieldValidate.h"
@interface CustomTextField : UITextField
// 抽象的策略
@property (nonatomic, strong) InputTextFieldValidate *inputValidate;
// 驗(yàn)證是否符合要求
- (BOOL)validate;
@end
#import "CustomTextField.h"
@implementation CustomTextField
- (BOOL)validate {
BOOL result = [self.inputValidate validateInputTextField:self];
if (!result) {
NSLog(@"---%@",self.inputValidate.attributeInputStr);
}
return result;
}
@end
業(yè)務(wù)調(diào)用
#import "ViewController.h"
#import "CustomTextField.h"
#import "LatterTextFieldValidate.h"
#import "NumberTextFieldValidate.h"
@interface ViewController () <UITextFieldDelegate>
@property (weak, nonatomic) IBOutlet CustomTextField *letterInput; /**< 字母輸入 */
@property (weak, nonatomic) IBOutlet CustomTextField *numberInput; /**< 數(shù)字輸入 */
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.letterInput.delegate = self;
self.numberInput.delegate = self;
// 初始化
self.letterInput.inputValidate = [LatterTextFieldValidate new];
self.numberInput.inputValidate = [NumberTextFieldValidate new];
}
- (IBAction)btnClick:(id)sender {
[self.view endEditing:YES];
}
#pragma mark - UITextFieldDelegate
- (void)textFieldDidEndEditing:(UITextField *)textField {
if ([textField isKindOfClass:[CustomTextField class]]) {
[(CustomTextField *)textField validate];
}
}
@end
4.使用場景
可以用于if/else和switch/case出現(xiàn)的地方,之后出現(xiàn)新的判斷算法,只需要新增一個(gè)具體的算法類。
5.優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
1、 策略模式提供了管理相關(guān)的算法族的辦法。策略類的等級結(jié)構(gòu)定義了一個(gè)算法或行為族。恰當(dāng)使用繼承可以把公共的代碼轉(zhuǎn)移到父類里面,從而避免重復(fù)的代碼。
2、 策略模式提供了可以替換繼承關(guān)系的辦法。繼承可以處理多種算法或行為。如果不是用策略模式,那么使用算法或行為的環(huán)境類就可能會(huì)有一些子類,每一個(gè)子類提供一個(gè)不同的算法或行為。但是,這樣一來算法或行為的使用者就和算法或行為本身混在一起。決定使用哪一種算法或采取哪一種行為的邏輯就和算法或行為的邏輯混合在一起,從而不可能再獨(dú)立演化。繼承使得動(dòng)態(tài)改變算法或行為變得不可能。
3、 使用策略模式可以避免使用多重條件轉(zhuǎn)移語句。多重轉(zhuǎn)移語句不易維護(hù),它把采取哪一種算法或采取哪一種行為的邏輯與算法或行為的邏輯混合在一起,統(tǒng)統(tǒng)列在一個(gè)多重轉(zhuǎn)移語句里面,比使用繼承的辦法還要原始和落后。
缺點(diǎn):
1、客戶端必須知道所有的策略類,并自行決定使用哪一個(gè)策略類。這就意味著客戶端必須理解這些算法的區(qū)別,以便適時(shí)選擇恰當(dāng)?shù)乃惴?。換言之,策略模式只適用于客戶端知道所有的算法或行為的情況。
2、 策略模式造成很多的策略類,每個(gè)具體策略類都會(huì)產(chǎn)生一個(gè)新類。有時(shí)候可以通過把依賴于環(huán)境的狀態(tài)保存到客戶端里面,而將策略類設(shè)計(jì)成可共享的,這樣策略類實(shí)例可以被不同客戶端使用。換言之,可以使用享元模式來減少對象的數(shù)量。
說明:目前只是對策略模式進(jìn)行的簡單整理,對定義和使用場景及優(yōu)缺點(diǎn)理解還不到位,Demo之后會(huì)更新,歡迎批評指正。