策略模式(Strategy)

基本理解

  • 面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。
  • 策略模式:它定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户。
  • 简单工厂模式需要让客户端认识两个类,而策略模式和简单工厂结合的用法,客户端只需要认识一个类就可以了。耦合更加降低。
  • 当不同的行为堆砌在一个类中时,就很难避免使用条件语句来选择合适的行为。将这些行为封装在一个个独立的Strategy类中,可以再使用这些行为的类中消除条件语句。
  • 策略模式就是用来封装算法的,但在实践中,我们发现用它来封装几乎任何类型的规则,只要在分析过程中听到了需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。
  • 在基本的策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象。
  • 面向对象软件设计中,我们可以把相关算法分离为不同的类,成为策略。
  • 策略模式中的一个关键角色是策略类,它为所有支持的或者相关的算法声明了一个共同接口。
  • 控制器和试图之间是一种基于策略模式的关系。

优点

  • 策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。
  • 策略模式的Stategy类层次为Context定义了一些列的可供重用的算法或行为。继承有助于析取出算法中的公共功能。
  • 策略模式的优点是简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。

使用场景

  • 一个类在其操作中使用多个条件语句来定义许多行为。我们可以把相关的条件分支移到他们自己的策略类中
  • 需要算法的各种变体
  • 需要避免把复杂的、与算法相关的数据结构暴露给客户端

例子

该例子主要利用策略模式来判断UITextField是否满足输入要求,比如输入的只能是数字,如果只是数字就没有提示,如果有其他字符则提示出错。验证字母也是一样。

首先,我们先定义一个抽象的策略类IputValidator。代码如下:

InputValidator.h

  	//
// InputValidator.h
// StrategyDemo
//
// Created by zhanggui on 15/8/7.
// Copyright (c) 2015年 zhanggui. All rights reserved.
// #import <Foundation/Foundation.h>
#import <UIKit/UIKit.h> static NSString * const InputValidationErrorDomain = @"InputValidationErrorDomain";
@interface InputValidator : NSObject //实际验证策略的存根方法
-(BOOL)validateInput:(UITextField *)input error:(NSError **)error;
@end

InputValidator.m

//
// InputValidator.m
// StrategyDemo
//
// Created by zhanggui on 15/8/7.
// Copyright (c) 2015年 zhanggui. All rights reserved.
// #import "InputValidator.h" @implementation InputValidator -(BOOL)validateInput:(UITextField *)input error:(NSError **)error
{
if (error) {
*error = nil;
}
return NO;
}
@end

这个就是一个策略基类,然后我们去创建两个子类NumericInputValidator和AlphaInputValidator。具体代码如下:

NumericIputValidator.h

//
// NumericInputValidator.h
// StrategyDemo
//
// Created by zhanggui on 15/8/7.
// Copyright (c) 2015年 zhanggui. All rights reserved.
// #import "InputValidator.h" @interface NumericInputValidator : InputValidator -(BOOL)validateInput:(UITextField *)input error:(NSError **)error;
@end

NumericIputValidator.m

//
// NumericInputValidator.m
// StrategyDemo
//
// Created by zhanggui on 15/8/7.
// Copyright (c) 2015年 zhanggui. All rights reserved.
// #import "NumericInputValidator.h" @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:&regError]; 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

AlphaInputValidator.h

//
// AlphaInputValidator.h
// StrategyDemo
//
// Created by zhanggui on 15/8/7.
// Copyright (c) 2015年 zhanggui. All rights reserved.
// #import "InputValidator.h" @interface AlphaInputValidator : InputValidator - (BOOL)validateInput:(UITextField *)input error:(NSError **)error;
@end

AlphaInputValidator.m

//
// AlphaInputValidator.m
// StrategyDemo
//
// Created by zhanggui on 15/8/7.
// Copyright (c) 2015年 zhanggui. All rights reserved.
// #import "AlphaInputValidator.h"
@implementation AlphaInputValidator -(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:&regError]; 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

他们两个都是InputValidator的子类。然后再定义一个CustomTextField:

CustomTextField.h

//
// CustomTextField.h
// StrategyDemo
//
// Created by zhanggui on 15/8/7.
// Copyright (c) 2015年 zhanggui. All rights reserved.
// #import <UIKit/UIKit.h>
@class InputValidator;
@interface CustomTextField : UITextField @property(nonatomic,strong)InputValidator *inputValidator; -(BOOL)validate;
@end

CustomTextField.m

//
// CustomTextField.m
// StrategyDemo
//
// Created by zhanggui on 15/8/7.
// Copyright (c) 2015年 zhanggui. All rights reserved.
// #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

最后在ViewController中测试是否完成验证

ViewController.m

//
// ViewController.m
// StrategyDemo
//
// Created by zhanggui on 15/8/7.
// Copyright (c) 2015年 zhanggui. All rights reserved.
// #import "ViewController.h"
#import "CustomTextField.h"
#import "NumericInputValidator.h"
#import "AlphaInputValidator.h"
@interface ViewController () @end @implementation ViewController - (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

结果:当我们输入的不满足条件的时候就会显示提示信息,而满足条件就不会有任何提示。

附:

最新文章

  1. MVC中使用Entity Framework 基于方法的查询学习笔记 (二)
  2. jQuery源码分析系列:Callback深入
  3. 0002 Oracle账户相关的几个语句
  4. 使用ThreadLocal、Apache的dbutils的QueryRunner和dbcp2数据库连接池的BasicDataSource封装操作数据库工具
  5. DB2 日期相减
  6. C# 对象的序列化与反序列化 (DataContractJsonSerializer)
  7. js弹出窗口总结6种弹窗方法
  8. 《JAVA学习笔记(14-1---14-7)》
  9. php:的图形计算器的面向对象的版本武器2
  10. 微信小程序scroll-view(或者其他view) 计算高度 px转rpx有关
  11. 003_python学习之 字符串前&#39;r&#39;的用法
  12. Stanford机器学习---第十一讲.异常检测
  13. Vim命令相关
  14. 27-1-LTDC-DMA2D—液晶显示简介
  15. HTML 标记 1
  16. 尚学堂java答案解析 第三章
  17. 【sql】之case when then else end
  18. 网站访问者UA检测及跳转
  19. In MySQL, a zero number equals any string
  20. Secure CRT 自动记录日志log配置

热门文章

  1. 在ASP.NET开发中容易忽略的2个小问题
  2. SplayTree伸展树的非递归实现(自底向上)
  3. 使用Service.Stack客户端编写redis pub sub的方法
  4. Hadoop入门进阶课程9--Mahout介绍、安装与应用案例
  5. MySQL安全问题(防范必知)
  6. 如何用参数化SQL语句污染你的计划缓存
  7. QCustomplot使用分享(六) 坐标轴和网格线
  8. Week3 博客阅读感想和代码复审
  9. 数论 - 欧拉函数模板题 --- poj 2407 : Relatives
  10. .Net配置文件——反射+配置文件存储类型实例