继上次的适配器模式后,这次说的是策略模式。
还是同样的套路,先来说说为什么要使用策略模式吧***
在实际的开发中,肯定会有多选一的情况,这时首先想到的肯定是 if-else 语句啦~如果有很多很多情况,我想就if-else都得写吐了吧 - _ -!!而且会显得代码特别繁琐,可读性差。
举一个栗子吧,登录界面中,验证邮箱、姓名、手机号、、、等等杂七杂八的条件时,就需要有选择性的验证,这就是所谓的多选一的情况,实际上邮箱、手机号、姓名等等在验证的时候都是验证文本框中的文字,这时就可以用策略模式来解决这个问题。
下图展示了策略模式的基本原理:
如图中所看到的+-+
context : 应用场景
(1)需要使用具体策略类(如ConcreteStrategyA类)中的算法
(2)需要持有一个Strategy实例变量
(3)需要与Strategy类之间交互并且进行数据传递
Strategy :抽象策略类
(1)定义一个公共接口,并且空实现。
(2)Context使用这个接口调用不同的算法
ConcreteStrategyA :具体策略类
以继承的方式实现具体的算法。
接下来就是以文本输入框的验证为例上代码啦~~~
(1)if-else方式
CustomedField类
.h
#import <UIKit/UIKit.h>
@interface CustomedField : UITextField
//初始化并返回实例对象
- (instancetype)initWithFrame:(CGRect)frame;
@end
.m
#import "CustomedField.h"
@implementation CustomedField
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
//实现***
}
return self;
}
@end
ViewController.m
#import "ViewController.h"
#import "CustomedField.h"
#define W [UIScreen mainScreen].bounds.size.width
@interface ViewController ()
<UITextFieldDelegate>
//邮箱文本输入框
@property CustomedField *emailField;
//电话号文本输入框
@property CustomedField *phoneNumberField;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self initTextField];
[self initButton];
}
//初始化文本输入框
- (void)initTextField{
//***
}
//初始化确认按钮级点击事件
- (void)initButton{
//***
}
- (void)touchButton:(UIButton *)button{
[self.view endEditing:YES];
}
//文本框代理
- (void)textFieldDidEndEditing:(UITextField *)textField{
NSString *str = nil;
if (textField == self.emailField) {
str = [self validateEmailField:textField];
if (str) {
NSLog(@"%@",str);
}
else{
NSLog(@"textfield不为空");
}
}
else if(textField == self.phoneNumberField)
{
str = [self validateEmailField:textField];
if (str) {
NSLog(@"%@",str);
}
else{
NSLog(@"textfield不为空");
}
}
//else if...
}
//验证算法(简单起见,只验证textfield是否为空)
- (NSString *)validateEmailField:(UITextField *)field {
NSString *str = nil;
if (field.text.length <= 0) {
str = @"没有输入";
}
return str;
}
- (NSString *)validatePhoneNumberField:(UITextField *)field {
NSString *str = nil;
if (field.text.length <= 0) {
str = @"没有输入";
}
return str;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
这里我只写了两个文本输入框,假如有成十成百个需要验证的,如果使用if-else就太麻烦啦~
(2)策略模式
①抽象策略类:TextFieldValidateStrategy类
.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface TextFieldValidateStrategy : NSObject
//当验证不通过时,读取错误信息
@property (nonatomic ,strong) NSString *errorMessageStr;
//验证策略,通过返回YES,不通过返回NO
- (BOOL)validateTextField:(UITextField *)field;
@end
#import "TextFieldValidateStrategy.h"
@implementation TextFieldValidateStrategy
//空实现验证策略
- (BOOL)validateTextField:(UITextField *)field{
return NO;
}
@end
②具体策略类
i > EmailTextFieldValidateStrategy类
.h
#import "TextFieldValidateStrategy.h"
@interface EmailTextFieldValidateStrategy : TextFieldValidateStrategy
//重载父类的验证方法
- (BOOL)validateTextField:(UITextField *)field;
@end
.m
#import "EmailTextFieldValidateStrategy.h"
@implementation EmailTextFieldValidateStrategy
- (BOOL)validateTextField:(UITextField *)field{
self.errorMessageStr = nil;
if (field.text.length <= 0) {
self.errorMessageStr = @"没有输入";
}
return self.errorMessageStr == nil ? YES : NO;
}
@end
ii > PhoneNumberTextFieldValidateStrategy类
.h
#import "TextFieldValidateStrategy.h"
@interface PhoneNumberTextFieldValidateStrategy : TextFieldValidateStrategy
//重载父类的验证方法
- (BOOL)validateTextField:(UITextField *)field;
@end
.m
#import "PhoneNumberTextFieldValidateStrategy.h"
@implementation PhoneNumberTextFieldValidateStrategy
- (BOOL)validateTextField:(UITextField *)field{
self.errorMessageStr = nil;
if (field.text.length <= 0) {
self.errorMessageStr = @"没有输入";
}
return self.errorMessageStr == nil ? YES : NO;
}
@end
③应用场景:CustomedField类
.h
#import <UIKit/UIKit.h>
#import "TextFieldValidateStrategy.h"
@interface CustomedField : UITextField
//初始化textfield,返回实例对象
- (instancetype)initWithFrame:(CGRect)frame;
//抽象策略的实例对象
@property (nonatomic,strong) TextFieldValidateStrategy *strategy;
//与Strategy类进行交互并且传递数据
- (BOOL)validate;
@end
.m (只增加了Validate方法)
- (BOOL)validate
{
return [self.strategy validateTextField:self];
}
ViewController.m
①在初始化文本输入框时,需要让其持有Strategy实例变量
如:
self.emailField.strategy = [EmailTextFieldValidateStrategy new];
phoneNumberField也是如此,若有多个还是如此=~=
②文本框代理有所改变
- (void)textFieldDidEndEditing:(UITextField *)textField{
CustomedField *field = (CustomedField *)textField;
if ([field validate] == NO) {
NSLog(@"%@",field.strategy.errorMessageStr);
}
else{
NSLog(@"验证成功");
}
}
这样就完成啦~是不是很简单呢,而且代码看起来也很干净~~~
有利即有弊+-+
策略模式可以简练if-else语句,让代码可读性增强,易于维护。
但是它只适用于已经知道了所有的算法的情况。。。换言之,客户端必须知道所有的算法,并且自行选择使用哪一个策略类 -_-~~~
说到这里,已经基本上完啦,有不对的或者有啥表达不当的敬请指正。谢谢大家~撒花~~~笔芯~~~