iOS策略设计模式实践

栏目: 后端 · 发布时间: 7年前

内容简介:情景:把一堆算法塞到同一段代码中,然后使用策略模式的使用可以粗暴的分为3个角色。它们的静态关系如下图所示:

情景:把一堆算法塞到同一段代码中,然后使用 if-else 或者 switch-case 条件语句来决定要使用哪个算法?这些算法可能是一堆相似的类函数或方法,用以解决相关的问题。例如验证数据输入的情形,数据本身可以是任何数据类型(如CGFloat,NSString,NSInteger等),每种数据类型需要不同的算法。如果把每一种算法封装成一个对象,那么就能消除根据数据类型决定使用什么算法的一堆 if-elseswitch-case 语句。 面向对象软件设计中,我们可以把相关算法分离为不同的类,成为策略,对应的 设计模式 称为策略模式。

何为策略模式

策略模式的使用可以粗暴的分为3个角色。

  1. 策略类,或者定义为策略接口、策略协议,它为所有支持的或相关的算法声明了一个共同接口。
  2. 策略对象:它会实现策略协议,策略对象通常存在多个,分别封装实现具体的算法。
  3. 场景(context)类对象:配置有一个具体策略对象的示例,场景对象使用策略接口调用由具体策略类定义的算法。

它们的静态关系如下图所示:

iOS策略设计模式实践

一组算法,或者说算法的一个层次结构,以ConcreteStrategy(A、B和C)类的形式,共享相同的AlgorithmInterface接口,这样Context就能使用相同的接口访问算法的各种变体。

Context的实例可以在运行时用不同的ConcreteStrategy对象进行配置,这可以理解成更换context对象的『内容』,因为变更是发生在对象的内部。

何时使用策略模式

在以下情形,考虑使用策略模式。

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

在UITextField中应用策略模式

类图设计如下图所示:

iOS策略设计模式实践

策略接口

这里策略类抽象了两个接口:

@protocol ACITextFieldInputValidator <NSObject>

- (BOOL)validateInput:(UITextField *)textField
    charactersInRange:(NSRange)range
    replacementString:(NSString *)string
                error:(NSError **)error;

- (BOOL)validateEndEditingInput:(UITextField *)textField error:(NSError **)error;

@end

其中

- (BOOL)validateInput:(UITextField *)textField
    charactersInRange:(NSRange)range
    replacementString:(NSString *)string
                error:(NSError **)error;

在UITextFieldDelegate的 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string 方法中进行验证。

- (BOOL)validateEndEditingInput:(UITextField *)textField error:(NSError **)error; 在UITextFieldDelegate的 - (void)textFieldDidEndEditing:(UITextField *)textField 方法中进行验证。

这里特殊说明一下:

接口中使用UITextField作为入参而不是使用NSString作为入参,是因为如果只用NSString值,那么策略对象中的动作就是单向的。就是说,验证器只能检查,然后返回结果,而不能修改原始值。而使用UITextField型的输入参数,就可以两全其美。验证器可以选择修改文本框的原始值(比如删除无效的值),或者只检查而不修改。

另一个问题是,如果输入值错误,为什么不引发一个NSException异常呢?这是因为在Cocoa Touch框架中,引发自己的异常然后再用 try-catch 语句块来捕捉,这非常耗资源,所以不推荐,返回NSError对象的开销相对较小。

场景

这里使用策略的场景是UITextField,在UITextField的子类InputValidateTextField中,声明一个遵循策略协议的对象属性。

@interface ACIInputValidateTextField : UITextField

@property (nonatomic, strong) id<ACITextFieldInputValidator> inputValidator;

- (BOOL)validateCharactersInRange:(NSRange)range
                replacementString:(NSString *)string
                            error:(NSError **)error;

- (BOOL)validateEndEditingWithError:(NSError **)error;

@end

同时,场景对象中会声明方法来处理调用策略对象的接口方法。具体示例如下:

@implementation ACIInputValidateTextField

- (BOOL)validateCharactersInRange:(NSRange)range
                replacementString:(NSString *)string
                            error:(NSError **)error {
    
    BOOL shouldChange = [self.inputValidator validateInput:self charactersInRange:range replacementString:string error:error];
    return shouldChange;
}

- (BOOL)validateEndEditingWithError:(NSError **)error {
    BOOL isValid = [self.inputValidator validateEndEditingInput:self error:error];
    return isValid;
}

@end

策略对象

策略对象,这里是遵循了策略协议的 TextFieldInputValidator 的对象。每个对象会实现TextFieldInputValidator的方法,其中封装了具体的策略实现。

具体代码示例详见 github InputValidator

如果觉得本文对你有帮助,就请用微信随意打赏我吧^_^

iOS策略设计模式实践


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Ajax Design Patterns

Ajax Design Patterns

Michael Mahemoff / O'Reilly Media / 2006-06-29 / USD 44.99

Ajax, or Asynchronous JavaScript and XML, exploded onto the scene in the spring of 2005 and remains the hottest story among web developers. With its rich combination of technologies, Ajax provides a s......一起来看看 《Ajax Design Patterns》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具