IOS 設(shè)計(jì)模式-策略

  • if - else 的問題
  • 策略模式的原理
  • 策略模式的使用
  • 策略模式的優(yōu)缺點(diǎn)
if-else的問題
#import "ViewController.h"

/**
 條件列表
 */
typedef enum : NSUInteger {
    
    EType_01,
    EType_02,
    EType_03,
    EType_04,
    EType_05,
    EType_06,
    EType_07,
    EType_08,
    EType_09,
    
} ETypes;

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    
    [super viewDidLoad];

    // 輸入條件
    ETypes type = EType_01;
    
    // 輸出條件
    NSString *showString = nil;
    
    
    if (type == EType_01) {
        
        // showString = ...
        
    } else if (type == EType_02) {
    
        // showString = ...
        
    } else if (type == EType_03) {
        
        // showString = ...
        
    } else if (type == EType_04) {
        
        // showString = ...
        
    } else if (type == EType_05) {
        
        // showString = ...
        
    } else if (type == EType_06) {
        
        // showString = ...
        
    } else if (type == EType_07) {
        
        // showString = ...
        
    } else if (type == EType_08) {
        
        // showString = ...
        
    } else if (type == EType_09) {
        
        // showString = ...
        
    } else {
    
        showString = @"";
    }
}

@end

if-else判斷特別多的時(shí)候,代碼邏輯就復(fù)雜了培慌,可讀性也很差。
也許我們會(huì)把這些判斷單獨(dú)放到一個(gè)類里面來進(jìn)行處理哈肖。

#import <Foundation/Foundation.h>

typedef enum : NSUInteger {
    
    EType_01,
    EType_02,
    EType_03,
    EType_04,
    EType_05,
    EType_06,
    EType_07,
    EType_08,
    EType_09,
    
} ETypes;

@interface EtypeValue : NSObject

+ (NSString *)type:(ETypes)type;

@end
#import "EtypeValue.h"

@implementation EtypeValue

+ (NSString *)type:(ETypes)type {

    // 輸出條件
    NSString *showString = nil;
    
    if (type == EType_01) {
        
        // showString = ...
        
    } else if (type == EType_02) {
        
        // showString = ...
        
    } else if (type == EType_03) {
        
        // showString = ...
        
    } else if (type == EType_04) {
        
        // showString = ...
        
    } else if (type == EType_05) {
        
        // showString = ...
        
    } else if (type == EType_06) {
        
        // showString = ...
        
    } else if (type == EType_07) {
        
        // showString = ...
        
    } else if (type == EType_08) {
        
        // showString = ...
        
    } else if (type == EType_09) {
        
        // showString = ...
        
    } else {
        
        showString = @"";
    }
    
    return showString;
}

@end

這樣抽離出來一個(gè)類瘦锹,我們需要用到的時(shí)候只要調(diào)用這個(gè)類的一個(gè)方法就可以了脆贵,但實(shí)際上在這個(gè)類的方法中残家,依然還是通過if-else判斷泣港,代碼量并沒有減少兽间,邏輯也沒有簡(jiǎn)化历葛,知識(shí)挪了一下位置而已.

策略模式的原理


義一系列的算法,把每一個(gè)算法封裝起來, 并且使它們可相互替換。本模式使得算法可獨(dú)立于使用它的客戶而變化嘀略。
*相同的輸入不同的輸出
下面是一個(gè)策略模式的具體實(shí)現(xiàn)恤溶,下面我們要做的是一個(gè)表單的輸入驗(yàn)證。
我們自定義的一個(gè)文本輸入CustomField

#import <UIKit/UIKit.h>
#import "InputValidator.h"

@interface CustomField : UITextField

/**
 *  抽象的策略
 */
@property (nonatomic, strong) InputValidator *validator;

/**
 *  初始化textField
 *
 *  @param frame
 *  @param inputValidator 驗(yàn)證策略
 *
 *  @return 實(shí)例對(duì)象
 */
- (instancetype)initWithFrame:(CGRect)frame;

/**
 *  驗(yàn)證輸入合法性
 *
 *  @return 是否合法,不合法,讀取InputValidator當(dāng)中的errorMessage
 */
- (BOOL)validate;

@end
#import "CustomField.h"

@interface CustomField ()

@end

@implementation CustomField

#pragma mark - 初始化
- (instancetype)initWithFrame:(CGRect)frame {
    
    self = [super initWithFrame:frame];
    if (self) {
    
        [self setup];
    }
    
    return self;
}

- (void)setup {

    UIView *leftView       = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, self.frame.size.height)];
    self.leftView          = leftView;
    self.leftViewMode      = UITextFieldViewModeAlways;
    
    self.font = [UIFont fontWithName:@"Avenir-Book" size:12.f];
    
    self.layer.borderWidth = 0.5f;
}

- (BOOL)validate {

    return [self.validator validateInput:self];
}

@end

下面我們接著定義一個(gè)抽象的策略類:

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface InputValidator : NSObject

/**
 *  策略的輸入
 *
 *  @param input
 *
 *  @return 如果為YES,表示測(cè)試通過,如果為NO,表示測(cè)試不通過
 */
- (BOOL)validateInput:(UITextField *)input;

/**
 *  當(dāng)validateInput為NO的時(shí)候,我們來讀取errorMessage
 */
@property (nonatomic, strong) NSString *errorMessage;

@end
#import "InputValidator.h"

@implementation InputValidator

- (BOOL)validateInput:(UITextField *)input {

    return NO;
}

@end

最后我們?cè)賹?shí)現(xiàn)具體的策略類帜羊,在此我們實(shí)現(xiàn)兩個(gè)策略類咒程,一個(gè)是電話驗(yàn)證,一個(gè)是email驗(yàn)證讼育。

#import "InputValidator.h"

@interface PhoneNumberValidator : InputValidator

/**
 *  重載了父類的驗(yàn)證方法
 */
- (BOOL)validateInput:(UITextField *)input;

@end
#import "PhoneNumberValidator.h"
#import "RegExCategories.h"

@implementation PhoneNumberValidator

- (BOOL)validateInput:(UITextField *)input {
    
    if (input.text.length <= 0) {
        
        self.errorMessage = @"沒有輸入";
        
    } else {
        
        BOOL isMatch = [input.text isMatch:RX(@"^((13[0-9])|(15[^4,\\D])|(18[0,0-9]))\\d{8}$")];
        if (isMatch == NO) {
            
            self.errorMessage = @"請(qǐng)輸入正確的手機(jī)號(hào)碼";
            
        } else {
            
            self.errorMessage = nil;
        }
    }
    
    return self.errorMessage == nil ? YES : NO;
}

@end
#import "InputValidator.h"

@interface EmailValidator : InputValidator

/**
 *  重載了父類的驗(yàn)證方法
 */
- (BOOL)validateInput:(UITextField *)input;

@end
#import "EmailValidator.h"
#import "RegExCategories.h"

@implementation EmailValidator

- (BOOL)validateInput:(UITextField *)input {
    
    if (input.text.length <= 0) {
        
        self.errorMessage = @"沒有輸入";
        
    } else {
        
        BOOL isMatch = [input.text isMatch:RX(@"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}")];
        if (isMatch == NO) {
            
            self.errorMessage = @"請(qǐng)輸入正確的郵箱";
            
        } else {
        
            self.errorMessage = nil;
        }
    }
    
    return self.errorMessage == nil ? YES : NO;
}

@end

那么我們使用中就可以是這樣的

#import "ViewController.h"
#import "UIButton+inits.h"
#import "CustomField.h"
#import "UIView+SetRect.h"
#import "RegExCategories.h"
#import "UIInfomationView.h"

#import "EmailValidator.h"
#import "PhoneNumberValidator.h"

@interface ViewController () <UITextFieldDelegate>

/**
 *  輸入郵箱的驗(yàn)證框
 */
@property (nonatomic, strong) CustomField  *emailField;

/**
 *  輸入電話號(hào)碼的驗(yàn)證框
 */
@property (nonatomic, strong) CustomField  *phoneNumberField;

/**
 *  驗(yàn)證email地址
 *
 *  @param input 輸入
 *
 *  @return 輸出結(jié)果
 */
- (NSString *)validateEmailInput:(UITextField *)input;

/**
 *  驗(yàn)證電話號(hào)碼
 *
 *  @param input 輸入
 *
 *  @return 輸出結(jié)果
 */
- (NSString *)validatePhoneNumberInput:(UITextField *)input;

@end

@implementation ViewController

- (void)viewDidLoad {
    
    [super viewDidLoad];

    // 初始化按鈕
    [self initButton];
    
    // 初始化驗(yàn)證框
    [self initCustomFields];
}

#pragma mark - 初始化文本輸入框
- (void)initCustomFields {
    
    
    self.emailField             = [[CustomField alloc] initWithFrame:CGRectMake(30, 80, Width - 60, 30)];
    self.emailField.placeholder = @"請(qǐng)輸入郵箱";
    self.emailField.delegate    = self;
    self.emailField.validator   = [EmailValidator new];
    [self.view addSubview:self.emailField];
    
    
    self.phoneNumberField             = [[CustomField alloc] initWithFrame:CGRectMake(30, 80 + 40, Width - 60, 30)];
    self.phoneNumberField.placeholder = @"請(qǐng)輸入電話號(hào)碼";
    self.phoneNumberField.delegate    = self;
    self.phoneNumberField.validator   = [PhoneNumberValidator new];
    [self.view addSubview:self.phoneNumberField];
}

#pragma mark - 初始化按鈕以及按鈕事件
- (void)initButton {
    
    UIButton *button = [UIButton createButtonWithFrame:CGRectMake(30, 30, 90, 30)
                                       buttonType:0
                                            title:@"Back"
                                              tag:0
                                           target:self
                                           action:@selector(buttonsEvent:)];
    [self.view addSubview:button];
}

- (void)buttonsEvent:(UIButton *)button {
    
    [self.view endEditing:YES];
}

#pragma mark - 文本框代理
- (void)textFieldDidEndEditing:(UITextField *)textField {
    
    CustomField *customField = (CustomField *)textField;
    
    if ([customField validate] == NO) {
        
        [UIInfomationView showAlertViewWithTitle:nil
                                         message:customField.validator.errorMessage
                               cancelButtonTitle:nil
                               otherButtonTitles:@[@"確定"]
                                    clickAtIndex:^(NSInteger buttonIndex) {
                                        
                                    }];
    }
}

@end

假如我們已有的代碼不能修改了帐姻,我們要驗(yàn)證一下郵編時(shí)我們只需要添加一個(gè)郵編驗(yàn)證的策略類就行了。你看看是不是很方便呢奶段。

策略模式的優(yōu)缺點(diǎn)

優(yōu)點(diǎn):可以將if-else這樣的判斷代碼精簡(jiǎn)成一行代碼饥瓷。
策略模式提供了對(duì)開放—封閉原則的完美支持,將算法封裝在獨(dú)立的strategy中痹籍,使得它們易于切換呢铆,易于理解,易于擴(kuò)展蹲缠。

策略模式中的算法也可以復(fù)用在系統(tǒng)的其他地方棺克,從而避免許多重復(fù)的復(fù)制粘貼工作鳖宾。

在策略模式中利用組合和委托來讓Context擁有執(zhí)行算法的能力,這也是繼承的一種更輕便的替代方案逆航。
缺點(diǎn):要使用策略模式鼎文,必須了解所有的strategy,必須了解各個(gè)strategy之間的不同點(diǎn)因俐,這樣才能選擇一個(gè)合適的strategy拇惋。比如,我們要選擇一種合適的旅游出行路線抹剩,必須先了解選擇飛機(jī)撑帖、火車、自行車等方案的細(xì)節(jié)澳眷。此時(shí)strategy要向客戶暴露它的所有實(shí)現(xiàn)胡嘿,這是違反最少知識(shí)原則的。使用策略模式的前提是要明確知道每個(gè)策略的細(xì)節(jié)钳踊。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末衷敌,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子拓瞪,更是在濱河造成了極大的恐慌缴罗,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祭埂,死亡現(xiàn)場(chǎng)離奇詭異面氓,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蛆橡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門舌界,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人泰演,你說我怎么就攤上這事呻拌。” “怎么了粥血?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵柏锄,是天一觀的道長(zhǎng)酿箭。 經(jīng)常有香客問我复亏,道長(zhǎng),這世上最難降的妖魔是什么缭嫡? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任缔御,我火速辦了婚禮,結(jié)果婚禮上妇蛀,老公的妹妹穿的比我還像新娘耕突。我一直安慰自己笤成,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布眷茁。 她就那樣靜靜地躺著炕泳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪上祈。 梳的紋絲不亂的頭發(fā)上培遵,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音登刺,去河邊找鬼籽腕。 笑死,一個(gè)胖子當(dāng)著我的面吹牛纸俭,可吹牛的內(nèi)容都是我干的皇耗。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼揍很,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼郎楼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起窒悔,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤箭启,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后蛉迹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體傅寡,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年北救,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了荐操。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡珍策,死狀恐怖托启,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情攘宙,我是刑警寧澤屯耸,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站蹭劈,受9級(jí)特大地震影響疗绣,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜铺韧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一多矮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦塔逃、人聲如沸讯壶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伏蚊。三九已至,卻和暖如春格粪,著一層夾襖步出監(jiān)牢的瞬間丙挽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工匀借, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留颜阐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓吓肋,卻偏偏與公主長(zhǎng)得像凳怨,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子是鬼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1 場(chǎng)景問題# 1.1 報(bào)價(jià)管理## 向客戶報(bào)價(jià)肤舞,對(duì)于銷售部門的人來講,這是一個(gè)非常重大均蜜、非常復(fù)雜的問題李剖,對(duì)不同的...
    七寸知架構(gòu)閱讀 5,079評(píng)論 9 62
  • 工廠模式類似于現(xiàn)實(shí)生活中的工廠可以產(chǎn)生大量相似的商品,去做同樣的事情囤耳,實(shí)現(xiàn)同樣的效果;這時(shí)候需要使用工廠模式篙顺。簡(jiǎn)單...
    舟漁行舟閱讀 7,758評(píng)論 2 17
  • 1 場(chǎng)景問題 1.1 報(bào)價(jià)管理 向客戶報(bào)價(jià),對(duì)于銷售部門的人來講充择,這是一個(gè)非常重大德玫、非常復(fù)雜的問題,對(duì)不同的客戶要...
    4e70992f13e7閱讀 3,087評(píng)論 2 16
  • 一 iOS中都有什么設(shè)計(jì)模式琴儿? 1.代理模式 2.觀察者模式 3.MVC模式 4.單例模式 5.策略模式 6.工廠...
    炸街程序猿閱讀 974評(píng)論 0 2
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)嘁捷,斷路器造成,智...
    卡卡羅2017閱讀 134,656評(píng)論 18 139