举例讲解iOS应用开发中对设计模式中的策略模式的使用

策略模式是一种常见的软件设计模式,这里简单得介绍一下策略模式并用IOS简单实现一下。
所谓的策略模式,顾名思义是要采用不同的策略的。一般来说,在不同的情况下,处理某一个问题的方法也不一样。比如说对字符串的排序和对数字的排序,虽然用的都是快排,但是显然不可能使用一段通用的代码。有人说java里面的compareTo可以做到,但如果考虑这么一个问题:同样是出门旅行,老年人身体虚弱,需要大量的休息,而孩子则是精力充沛,希望玩到更多的景点。如何在同一模式下表达以上信息、采用合理的设计模式进行封装而不是大量重写类似的代码,就需要学习并采用策略模式。

例子
该例子主要利用策略模式来判断UITextField是否满足输入要求,比如输入的只能是数字,如果只是数字就没有提示,如果有其他字符则提示出错。验证字母也是一样。
首先,我们先定义一个抽象的策略类IputValidator。代码如下:
InputValidator.h

代码如下:

#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

代码如下:

#import "InputValidator.h"

@implementation InputValidator

-(BOOL)validateInput:(UITextField *)input error:(NSError **)error
{
    if (error) {
        *error = nil;
    }
    return NO;
}
@end

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

代码如下:

#import "InputValidator.h"

@interface NumericInputValidator : InputValidator

-(BOOL)validateInput:(UITextField *)input error:(NSError **)error;
@end

NumericIputValidator.m

代码如下:

#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

代码如下:

#import "InputValidator.h"

@interface AlphaInputValidator : InputValidator

- (BOOL)validateInput:(UITextField *)input error:(NSError **)error;
@end

AlphaInputValidator.m

代码如下:

#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

代码如下:

#import <UIKit/UIKit.h>
@class InputValidator;
@interface CustomTextField : UITextField

@property(nonatomic,strong)InputValidator *inputValidator;

-(BOOL)validate;
@end

CustomTextField.m

代码如下:

#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

代码如下:

#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

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

优点

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

使用场景

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

总结
再总结一下策略方法的实现,本质上就是需要完成一个事情(出行),但是并不清楚需要使用怎样的策略,所以封装出一个函数,能够把需要的策略(young OR old)作为参数传递进来,并且使用相应的策略完成这个事件的处理。

最后简单谈一谈个人对于策略模式和面向对象中多态的思想的理解,首先多态是高层次,高度抽象的概念,独立于语言之外,是面向对象思想的精髓,而策略模式只是一种软件设计模式,相对而言更加具体,而且具体实现依赖于具体的编程语言,比如OC和java的实现方法并不相同,是language-dependent的。其次,多态更多强调的是,不同的对象调用同一个方法会得到不同的结果,而策略模式更多强调的是,同一个对象(事实上这个对象本身并不重要)在不同情况下执行不同的方法,而他们的实现方式又是高度类似的,即共享同一个父类并且各自重写父类的方法。

以上观点纯属个人愚见,欢迎大牛指正,互相交流。

(0)

相关推荐

  • iOS App使用设计模式中的模板方法模式开发的示例

    模板方法模式的核心思想就是通过把不变的行为搬移到超类,去除子类中的重复代码来体现它的优势.其实,模板方法模式就是提供了一个很好的代码复用平台. 首先,还是先简单看一下定义: 模板方法模式,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 下面和给大家展示一下类的结构图: 其实,结构很简单,只有两层关系,核心思想就是把公共方法向上提到父类中.代码实现起来也不复杂.下面还是老样子,向大家简单展示一下代码如何实现. 首先是一

  • 深入解析设计模式中的装饰器模式在iOS应用开发中的实现

    装饰器模式可以在不修改代码的情况下灵活的为一对象添加行为和职责.当你要修改一个被其它类包含的类的行为时,它可以代替子类化方法. 一.基本实现 下面我把类的结构图向大家展示如下: 让我们简单分析一下上面的结构图,Component是定义一个对象接口,可以给这些对象动态地添加职责.ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责.Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需

  • 详解iOS应用开发中使用设计模式中的抽象工厂模式

    概述 我们知道简单工厂模式的优点是去除了客户端与具体产品的依赖,缺点是违反了"开放-关闭原则":工厂方法模式克服了简单工厂模式的缺点,将产品的创建工作放到具体的工厂类,每个工厂类负责生成一个产品.但是在实际应用中,一个工厂类只创建单个产品的情况很少,一般一个工厂类会负责创建一系列相关的产品,如果我们要设计这样的系统,工厂方法模式显然不能满足应用的需求,本章要介绍的抽象工厂模式,可以很好地解决一系列产品创建的问题. 定义 "提供一个创建一系列相关或相互依赖对象的接口,而无需指定

  • iOS App设计模式开发中对建造者模式的运用实例

    定义          "将一个复杂对象的构建与它的表现分离,使得同样的构建过程可以创建不同的表现". 看这个概念,可能感觉很是抽象,能看懂但是不知道有什么用.我们打一个比方来理解上面的定义.打比方之前,咱们先来聊聊这个设计模式是干什么用的?我们为什么要用这个模式呢?建造者模式负责将构建复杂对象的过程和它的部件解耦,也就是过程和部件的解耦.比如说汽车,是一个很复杂的对象,它有很多的部件,车轮.发动机.座椅.车门.油箱等等:它的组装过程也很复杂(需要专业人士按步骤进行装配),建造者模式就

  • iOS App设计模式开发中对迭代器模式的使用示例

    何为迭代器模式? 迭代器提供了一种顺序访问集合对象中元素的方法,而无需暴漏结构的底层表示和细节.遍历集合中元素的职能从集合本身转移到迭代器对象.迭代器定义了一个用于访问集合元素并记录当前元素的接口.不同的迭代器可以执行不同的策略. 例子 说了这么多,下面给大家展示一下类关系图. 上图中Client的右边是迭代器,左边是具体迭代的类型,在迭代器内部对具体需要迭代的类型进行了引用,还算不难理解吧,呵呵.其实,看起来是为了对具体类型进行解耦.好啦,下面给出具体的代码实现,简单的模拟了迭代器模式. 注意

  • 实例解析设计模式中的外观模式在iOS App开发中的运用

    外观模式(Facade),为子系统中的一组接口提供一个一致的界面,此模式定义 一个高层接口,这个接口使得这一子系统更加容易使用. 下面给大家展示一下类的结构图,想必大家一看就明白了: 其实这个模式中,没有类与类之间的继承关系,只是进行了简单的类引用,统一了对外的接口而已.看起来是不是很简单?废话不多说了,下面简单向大家展示一下代码吧! 注意:本文所有代码均在ARC环境下编译通过. SubSystemOne类接口 复制代码 代码如下: #import <Foundation/Foundation.

  • 设计模式开发中的备忘录模式在iOS应用开发中的运用实例

    何为备忘录模式? 在响应某些事件时,应用程序需要保存自身的状态,比如当用户保存文档或程序退出时.例如,游戏退出之前,可能需要保存当前会话的状态,如游戏等级.敌人数量.可用武器的种类等.游戏再次打开时,玩家可以从离开的地方接着玩.很多时候,保存程序的状态真的不需要什么特别巧妙的方法.任何简单有效的方法都可以,但是同时,保存信息应该只对原始程序有意义.原始程序应该是能够解码它所保存文档中的信息的唯一实体.这就是备忘录模式应用于游戏.文字处理等程序的软件设计中的方式,这些程序需要保存当前上下文的复杂状

  • 解析iOS应用开发中对设计模式中的抽象工厂模式的实现

    概述 抽象工厂模式是对象的创建模式,它是工厂方法模式的进一步推广. 假设一个子系统需要一些产品对象,而这些产品又属于一个以上的产品等级结构.那么为了将消费这些产品对象的责任和创建这些产品对象的责任分割开来,可以引进抽象工厂模式.这样的话,消费产品的一方不需要直接参与产品的创建工作,而只需要向一个公用的工厂接口请求所需要的产品. 通过使用抽象工厂模式,可以处理具有相同(或者相似)等级结构中的多个产品族中的产品对象的创建问题.如下图所示: 根据产品角色的结构图,就不难给出工厂角色的结构设计图. 可以

  • iOS App设计模式开发中策略模式的实现示例

    这次介绍一下策略模式(Strategy Pattern),相比之下是一种比较简单的模式.它也叫政策模式(Policy Pattern). 策略模式使用的就是面向对象的继承和多态机制,其他的没有什么玄机.策略模式适合使用在: 1. 多个类只有在算法或行为上稍有不同的场景. 2. 算法需要自由切换的场景. 3. 需要屏蔽算法规则的场景. 使用策略模式当然也有需要注意的地方,那么就是策略类不要太多,如果一个策略家族的具体策略数量超过4个,则需要考虑混合模式,解决策略类膨胀和对外暴露问题.在实际项目中,

  • 详解iOS App设计模式开发中对于享元模式的运用

    享元模式的概念 在面向对象软件设计中,利用公共对象不仅能节省资源还能提高性能.共享的对象只能提供某些内在的信息,而不能用来识别对象.专门用于设计可共享对象的一种设计模式叫做享元模式(Flyweight pattern). 实现享元模式需要两个关键组件,通常是可共享的享元对象和保存他们的池.某种中央对象维护这个池,并从它返回适当的实例. 运用共享技术有效地支持大量细粒度的对象. 公共交通(如公共汽车)已有一百多年的历史了.大量去往相同方向的乘客可以分担保有和经营车辆(如公共汽车)的费用.公共汽车有

  • iOS App设计模式开发中对interpreter解释器模式的运用

    解释器模式 今天和大家分享的模式是解释器模式. 首先介绍一下解释器模式适合解决哪类问题. 其实,解释器模式需要解决的问题是,如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言的句子.这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题. 就应用的例子来说,例如正则表达式就是它的一种具体应用,解释器可以为正则表示定义一个文法,如何表示一个特定的正则表达式,以及如何解释这个正则表达式. 解释器模式的类结构图如下. 图中的结构也比较好理解,解释器方法抽

  • iOS App的设计模式开发中对State状态模式的运用

    1.概述 在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理.最直接的解决方案是将这些所有可能发生的情况全都考虑到.然后使用if... ellse语句来做状态判断来进行不同情况的处理.但是对复杂状态的判断就显得"力不从心了".随着增加新的状态或者修改一个状体(if else(或switch case)语句的增多或者修改)可能会引起很大的修改,而程序的可读性,扩展性也会变得很弱.维护也会很麻烦.那么我就考虑只修改自身状态的模式. 例子1:按钮来控制一个电梯的状态,一个电梯开们,

随机推荐