zoukankan      html  css  js  c++  java
  • iOS设计模式之策略模式

    策略模式(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
    

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

    附:

  • 相关阅读:
    WPF杂难解 图片模糊的暂时解决方案
    wpf学习笔记 NotifyPropertyChanged实现数据变化自动更新UI
    WPF杂难解 粘贴板复制GIF图片时丢失透明背景
    WPF杂难解 RichTextBox粘贴图片地址处理,并保存的问题
    wpf学习笔记 依赖属性
    WPF杂难解 中文字体显示模糊
    雪花型,支架型,和桥型 的区别
    BI工具对比
    关于javac不是内部命令的解决办法
    转载 android listview getview() 反复调用
  • 原文地址:https://www.cnblogs.com/zhanggui/p/4709967.html
Copyright © 2011-2022 走看看