iOS设计模式(1)策略模式

1.定义

策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变法独立于使用算法的客户。 —《Head First 设计模式》

2.UML图

iOS设计模式(1)策略模式_第1张图片
屏幕快照 2018-04-02 下午10.20.30.png

Context类可以理解成是业务场景,其包含了一个strategy属性,类型是Strategy,还有一个contextInterface的方法,用于执行Straetegy中的algrithmInterface方法(多态)。
Strategy是一个抽象基类,其中包含了一个algorithmInterface的抽象方法。
StrategyAStrategyBStrategyC类是继承自Strategy的具体算法类,algrithmInterface实现了具体的algrithmInterface方法。

3.使用

InputTextFieldValidate抽象算法类即Strategy

#import 

@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]*$ 从开头(^)到结尾($), 有效字符集([a-zA-Z])或者更多(*)个字符
    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])];
    
    // 进行判断,匹配不符合表示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 = @"数值不能是空的";
        return nil;
    }
    
    // ^[a-zA-Z]*$ 从开头(^)到结尾($), 有效字符集([a-zA-Z])或者更多(*)个字符
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^[0-9]*$" options:NSRegularExpressionAnchorsMatchLines error:nil];
    
    NSUInteger numberOfMatches = [regex numberOfMatchesInString:[textField text] options:NSMatchingAnchored range:NSMakeRange(0, [[textField text] length])];
    
    // 进行判断,匹配不符合表示0的话, 就走下面的逻辑
    if (numberOfMatches == 0) {
        self.attributeInputStr = @"不全是数字, 输入有误,请重新输入";
    } else {
        self.attributeInputStr = @"输入数字,全部是字母";
    }
    
    return self.attributeInputStr == nil ? YES : NO;
}

@end

CustomTextField即Context类

#import 
#import "InputTextFieldValidate.h"

@interface CustomTextField : UITextField

// 抽象的策略
@property (nonatomic, strong) InputTextFieldValidate *inputValidate;

// 验证是否符合要求
- (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

业务调用

#import "ViewController.h"
#import "CustomTextField.h"
#import "LatterTextFieldValidate.h"
#import "NumberTextFieldValidate.h"

@interface ViewController () 

@property (weak, nonatomic) IBOutlet CustomTextField *letterInput; /**< 字母输入 */
@property (weak, nonatomic) IBOutlet CustomTextField *numberInput; /**< 数字输入 */

@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出现的地方,之后出现新的判断算法,只需要新增一个具体的算法类。

5.优缺点

优点:

1、 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码转移到父类里面,从而避免重复的代码。

2、 策略模式提供了可以替换继承关系的办法。继承可以处理多种算法或行为。如果不是用策略模式,那么使用算法或行为的环境类就可能会有一些子类,每一个子类提供一个不同的算法或行为。但是,这样一来算法或行为的使用者就和算法或行为本身混在一起。决定使用哪一种算法或采取哪一种行为的逻辑就和算法或行为的逻辑混合在一起,从而不可能再独立演化。继承使得动态改变算法或行为变得不可能。

3、 使用策略模式可以避免使用多重条件转移语句。多重转移语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重转移语句里面,比使用继承的办法还要原始和落后。

缺点:

1、客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。

2、 策略模式造成很多的策略类,每个具体策略类都会产生一个新类。有时候可以通过把依赖于环境的状态保存到客户端里面,而将策略类设计成可共享的,这样策略类实例可以被不同客户端使用。换言之,可以使用享元模式来减少对象的数量。

说明:目前只是对策略模式进行的简单整理,对定义和使用场景及优缺点理解还不到位,Demo之后会更新,欢迎批评指正。

你可能感兴趣的:(iOS设计模式(1)策略模式)