iOS開發系列-Strategy模式

前言

在軟件工程中,設計模式(Design Pattern)是對軟件設計中普遍存在(反復出現)的各種問題,所提出的解決方案。

策略模式(Strategy Pattern)中定義一系列算法,并將每一個算法封裝起來,使使它們可以相互替換,策略模式讓算法獨立于它的客戶而變化。

下面我會就iOS實際開發中的case, 舉例說明Strategy模式的在開發中的具體應用。

Case Study:

在開發中, 我們會遇到各種表單的提交需求, 在實際需求中,表單提交之前一般都需要檢查一下所填寫的數據的有效性。這些對于特定類型的數據的有效性檢查,可能在程序中被反復用到。下面我就以開發中必不可少的用戶登錄功能,來看看Strategy模式的具體應用。

以email方式登錄為例。你至少需要檢查email和password輸入的有效性。在修改email或者修改password時, 你又需要使用email和password數據有效性的檢查邏輯。對于這種多于一次使用邏輯,基于DRY(Don't Repeat Youself)原則,我們需要封裝起來。


  • 首先我們把檢測數據的行為抽象一下,定義一個Validator Protocol。Validator我們可以稱為策略的抽象

    protocol Validator {  func isValid(text: String?) -> Bool}
  • 有策略的抽象,那策略的實現在哪里。ok,實現來了。我們定義EmailValidator類,讓它來實現Validator

    class EmailValidator: Validator {  func isValid(text: String?) -> Bool {      let regEx = "[A-Z0-9a-z._%+-][email protected][A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
          if let text = text {          let entryTest = NSPredicate(format: "SELF MATCHES %@", regEx)          return entryTest.evaluate(with: text)
          }      return false
      }
    }
  • 另一個PasswordValidator類

    class PasswordValidator: Validator {  func isValid(text: String?) -> Bool {      let regEx = "[A-Z0-9a-z._%+-;/><#]{6,30}"
          if let text = text {          let entryTest = NSPredicate(format: "SELF MATCHES %@", regEx)          return entryTest.evaluate(with: text)
          }      return false
      }
    }
  • 這時候我們需要一個ValidatorManager來根據用戶的條件,選擇調用哪個策略的實現。

    enum ValidationType: Int {  case Email = 0
      case Password}class ValidationManager {
    
      private lazy var validators: [Validator] = [EmailValidator(), PasswordValidator()]  func validationForText(text: String?, withValidationType validationType: ValidationType) -> Bool {      return validators[validationType.rawValue].isValid(text: text)
      }
    }
  • 在LoginViewController具體的調用時這樣子的:

      private lazy var validationManager = ValidationManager()  @IBAction func tapLoginButton(_ sender: UIButton) {      let emailValidation = validationManager.validationForText(text: emailField.text, withValidationType: .Email)      let passValidation = validationManager.validationForText(text: passwordField.text, withValidationType: .Password)      if emailValidation && passValidation {          // Log in successfully and enter main view
              performSegue(withIdentifier: "ShowMainView", sender: self)
          } else {          // validation failed. You can do anything you want to alert user.
              let alert = UIAlertController(title: "Failed", message: "Email or password is not valid.", preferredStyle: .alert)          let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
              alert.addAction(cancelAction)
              present(alert, animated: true, completion: nil)
          }
      }

總結

  • 第一步:你需要把你要做的事情抽象,用protocol來表示。 - 策略的抽象

  • 第二步:你要做的事情在不同情況下肯定會有不同具體實現,創造不同類來實現你的protocol。 - 策略的具體實現

  • 第三布:創建一個Manager來統一調配你的具體策略的實現。這個Manager會開放一個接口,滿足你調用的最小充要條件。Manager會根據你的條件,決定具體使用什么策略。

  • 最后一步:在你需要的地方使用Manager來實現你要做的事情吧。



文/DEREK_ZHOU(簡書作者)




上一篇: 如果恨一個程序員,忽悠他去做iOS開發

下一篇: 蘋果這更新簡直速度:iOS 10.2.1第2個測試版發布

分享到: 更多
黑桃棋牌 北京pk10日赚两百方法 双色球开奖规则 重庆时时彩走势图 极速时时心得 重庆时时彩计划软件手机版 2018最新捕鱼游戏大全 北京pk10冠军选号技巧 时时彩龙虎合是骗局么 龙虎赢钱的规律技巧 捕鱼赢现金 欢乐生肖平台哪家好 澳客竞彩 河北时时软件手机版下载 MG娱乐登录 重庆时时彩龙虎被骗