iOS架构师_策略模式

什么是策略设计模式?

概念:定义一系列的算法,并且将每个算法封装起来,算法之间还可以互相替换。这种设计模式称为策略模式。

为了解决if-else和switch-case的问题,在实际开发中,较长的if-else会使代码阅读困难。

这里写图片描述

代码示例:下面是一个简单的if-else代码

Demo1

#import "ViewController.h"
typedef NS_ENUM(NSInteger) {
    Count01,
    Count02,
    Count03,
    Count04,
    Count05,
}EnumCount;

@interface ViewController ()

@end

@implementation ViewController

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {  
    EnumCount count = Count04;//声明枚举,并给了一个固定的输入值
    if (count == 1) {
        NSLog(@"count = %lu",count);

    } else if (count == 2) {
        NSLog(@"count = %lu",count);

    }else if (count == 3) {
        NSLog(@"count = %lu",count);

    }else if (count == 4) {
        NSLog(@"count = %lu",count);

    } else {
        NSLog(@"count = %lu",count);
    }
}
@end

我们使用正常的代码抽离方式对其优化分离。

创建一个NSObject的类,Logic

Logic.h

#import <Foundation/Foundation.h>

typedef NS_ENUM(NSInteger) {
    Count01,
    Count02,
    Count03,
    Count04,
    Count05,
}EnumCount;

@interface Logic : NSObject

+ (NSUInteger)logic:(NSUInteger)integer;

@end

Logic.m

#import "Logic.h"

@implementation Logic
+ (NSUInteger)logic:(NSUInteger)integer {
    NSUInteger num;
    if (integer == 1) {
        num = 1;

    } else if (integer == 2) {
        num = 2;

    }else if (integer == 3) {
        num = 3;

    }else if (integer == 4) {
        num = 4;

    } else {
        num = 0;
    }
    return num;
}
@end

那么修改ViewController如下

#import "ViewController.h"
#import "Logic.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    EnumCount count = Count04;
    NSUInteger integer = [Logic logic:count];
    NSLog(@"integer = %lu", integer);
}
@end

那么如何使用策略模式呢?

新建继承自NSObject 的 BaseType类

BaseType.h文件

#import <Foundation/Foundation.h>

typedef NS_ENUM(NSInteger) {
    Count01,
    Count02,
    Count03,
    Count04,
    Count05,
}EnumCount;

@interface BaseType : NSObject
//返回计数结果
+(NSUInteger)backCountResult;
@end

BaseType.m

#import "BaseType.h"

@implementation BaseType
//抽象方法
+(NSUInteger)backCountResult {
    //编写代码
    return nil;
}
@end

创建继承自BaseType的子类CountTypes01

CountTypes01.h

#import "BaseType.h"

@interface CountTypes01 : BaseType

@end

CountTypes01.m

#import "CountTypes01.h"

@implementation CountTypes01

+ (NSUInteger)backCountResult {
    // 编写代码
    return 10;
}
@end

那么修改ViewController如下

#import "ViewController.h"
#import "CountTypes01.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSUInteger integer = [CountTypes01 backCountResult];

    NSLog(@"integer = %lu", integer);

}
@end

优缺点

策略模式的优点是能解决代码的耦合度,但是它是有牺牲的,为了解决代码耦合度,我们需要创建更多的类。

这里写图片描述

Demo2

需求:验证两个textField的输入条件

这里写图片描述

初始代码:
ViewController.m

#import "ViewController.h"

@interface ViewController () <UITextFieldDelegate>
@property (weak, nonatomic) IBOutlet UITextField *letterInput; /**< 字母输入 */
@property (weak, nonatomic) IBOutlet UITextField *numberInput; /**< 数字输入 */
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.letterInput.delegate = self;
    self.numberInput.delegate = self;
}

- (IBAction)btnClick:(id)sender {
    [self.view endEditing:YES];
}

#pragma mark - UITextFieldDelegate
- (void)textFieldDidEndEditing:(UITextField *)textField {
    if (textField == self.letterInput) {
        // 验证它的输入值, 确保它输入的是字母
        NSString *outputLatter = [self validateLatterInput:textField];
        if (outputLatter) {
            NSLog(@"---%@",outputLatter);
        }else {
            NSLog(@"---输入是空的");
        }

    } else if (textField == self.numberInput) {
       // 验证它的输入值, 确保它输入的是数字
        NSString *outputNumber = [self validateNumberInput:textField];
        if (outputNumber) {
            NSLog(@"---%@",outputNumber);
        }else {
            NSLog(@"---输入是空的");
        }
    }
}

#pragma mark - 验证输入
- (NSString *)validateLatterInput:(UITextField *)textField {
    if (textField.text.length == 0) {
        return nil;
    }

    // ^[a-zA-Z]*$ 从开头(^)到结尾($), 有效字符集([a-zA-Z])或者更多(*)个字符
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^[a-zA-Z]*$" options:NSRegularExpressionAnchorsMatchLines error:nil];
    //NSMatchingAnchored 从开始处就进行极限匹配
    NSUInteger numberOfMatches = [regex numberOfMatchesInString:[textField text] options:NSMatchingAnchored range:NSMakeRange(0, [[textField text] length])];

    NSString *outLatter = nil;
    // 进行判断,匹配不符合表示0的话, 就走下面的逻辑
    if (numberOfMatches == 0) {
        outLatter = @"不全是字母, 输入有误,请重新输入";
    } else {
        outLatter = @"输入正确,全部是字母";
    }

    return outLatter;
}

- (NSString *)validateNumberInput:(UITextField *)textField {
    if (textField.text.length == 0) {
        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])];

    NSString *outLatter = nil;
    // 进行判断,匹配不符合表示0的话, 就走下面的逻辑
    if (numberOfMatches == 0) {
        outLatter = @"不全是数字, 输入有误,请重新输入";
    } else {
        outLatter = @"输入正确,全部是数字";
    }

    return outLatter;

}


@end

我们知道,所有的设计模式都是为了代码解耦合所使用的,代价肯定是需要创建其他的类,将代码分离。

那么我们如何使用策略模式来优化代码呢?

首先我们创建一个继承自NSObject的抽象类:InputTextFieldValidate

InputTextFieldValidate.h

#import <UIKit/UIKit.h>

@interface InputTextFieldValidate : NSObject
// 策略输入 YES 表示测试通过.No 表示测试不通过
- (BOOL)validateInputTextField:(UITextField *)textField;

@property (nonatomic, copy) NSString *attributeInputStr; /**< 属性字符串 */
@end

InputTextFieldValidate.m

#import "InputTextFieldValidate.h"

@implementation InputTextFieldValidate
- (BOOL)validateInputTextField:(UITextField *)textField {
    return NO;
}
@end

再次创建一个继承自InputTextFieldValidate的类:LatterTextFieldValidate

LatterTextFieldValidate.h

#import "InputTextFieldValidate.h"

@interface LatterTextFieldValidate : InputTextFieldValidate

@end

LatterTextFieldValidate.m

#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])];

//    NSString *outLatter = nil;
    // 进行判断,匹配不符合表示0的话, 就走下面的逻辑
    if (numberOfMatches == 0) {
        self.attributeInputStr = @"不全是字母, 输入有误,请重新输入";
    } else {
        self.attributeInputStr = @"输入正取,全部是字母";
    }

    return self.attributeInputStr == nil ? YES : NO;
}
@end

再次创建一个继承自InputTextFieldValidate的类:NumberTextFieldValidate

NumberTextFieldValidate.h

#import "InputTextFieldValidate.h"

@interface NumberTextFieldValidate : InputTextFieldValidate

@end

NumberTextFieldValidate.m

#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])];

    //    NSString *outLatter = nil;
    // 进行判断,匹配不符合表示0的话, 就走下面的逻辑
    if (numberOfMatches == 0) {
        self.attributeInputStr = @"不全是数字, 输入有误,请重新输入";
    } else {
        self.attributeInputStr = @"输入数字,全部是字母";
    }

    return self.attributeInputStr == nil ? YES : NO;
}

@end

然后创建一个继承自UITextField的类:CustomTextField(自定义的TextField)

CustomTextField.h

#import <UIKit/UIKit.h>
#import "InputTextFieldValidate.h"

@interface CustomTextField : UITextField

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

// 验证是否符合要求
- (BOOL)validate;
@end

CustomTextField.m

#import "CustomTextField.h"

@implementation CustomTextField

- (BOOL)validate {
    BOOL result = [self.inputValidate validateInputTextField:self];

    if (!result) {
        NSLog(@"---%@",self.inputValidate.attributeInputStr);
    }

    return result;
}
@end

ViewController.m就简洁多了,修改如下:

#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; /**< 数字输入 */
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    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

优点:控制器代码简洁,分离代码复用性高,逻辑清晰,方便拓展。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值