iOS设计模式-策略模式

13 阅读3分钟

思想

把“算法/行为”从“使用它的类”中抽离出来,让客户端在运行时动态切换策略,而不需要修改 Context 的代码。(遵循开闭原则——对扩展开放,对修改封闭)

三个角色

协议:行为抽象

策略者:定义和实现各自的行为策略

上下文统筹者:针对各场景,切换对应的策略者,执行同一行为。

常用场景

庞大的 if-else / switch 语句,每个case都有自己的处理逻辑。

  • 支付场景(微信、支付宝、苹果、银行卡等)
  • 表单输入验证(手机号、邮箱、身份证、密码格式等)
  • 社交分享平台
  • 排序算法(按价格、销量、距离等)

模板

// 1. 抽象策略(协议)
protocol Strategy {
    func execute(data: [Int]) -> [Int]   // 示例:对数据 进行某种处理
}

// 2. 具体策略 A、B、C...
class ConcreteStrategyA: Strategy { ... }
class ConcreteStrategyB: Strategy { ... }

// 3. 上下文(Context)持有策略引用
class Context {
    private var strategy: Strategy
    
    init(strategy: Strategy) {
        self.strategy = strategy
    }
    
    func setStrategy(_ strategy: Strategy) {
        self.strategy = strategy
    }
    
    func doSomething(with data: [Int]) -> [Int] {
        return strategy.execute(data: data)   // 委托给当前策略 执行
    }
}

支付场景 示例

普通代码

面向过程编程

class OrderPayManager{
    func pay(way: Int){
        if way == .alipay {
            alipay()
        }else if way == .wxPay {
            wxpay()
        }else if {
            ...
        }
    }

    func alipay(){
        AliSDK()
        ...
    }
    
    func wxpay(){
        wxSDK()
        ...
    }
}

策略模式封装

  1. 抽象策略协议
protocol PaymentStrategy {
    func pay(amount: Double, completion: @escaping (Bool, String) -> Void)
}
  1. 具体策略实现
class AlipayStrategy: PaymentStrategy {
    func pay(amount: Double, completion: @escaping (Bool, String) -> Void) {
        print("🔸 支付宝支付 \(amount) 元")
        // 真实项目中这里调用支付宝 SDK
        completion(true, "支付宝支付成功")
    }
}

class WechatPayStrategy: PaymentStrategy {
    func pay(amount: Double, completion: @escaping (Bool, String) -> Void) {
        print("🔸 微信支付 \(amount) 元")
        // 调用微信支付 SDK
        completion(true, "微信支付成功")
    }
}

class ApplePayStrategy: PaymentStrategy {
    func pay(amount: Double, completion: @escaping (Bool, String) -> Void) {
        print("🔸 Apple Pay \(amount) 元")
        // 调用 PKPaymentAuthorizationViewController
        completion(true, "Apple Pay 支付成功")
    }
}
  1. 上下文(订单支付类)
class Order {
    private var paymentStrategy: PaymentStrategy
    
    init(paymentStrategy: PaymentStrategy) {
        self.paymentStrategy = paymentStrategy
    }
    
    // 切换支付方式
    func changePaymentMethod(to strategy: PaymentStrategy) {
        self.paymentStrategy = strategy
    }
    
    // 支付
    func checkout(amount: Double) {
        print("📦 订单金额:\(amount) 元")
        paymentStrategy.pay(amount: amount) { success, message in
            if success {
                print("🎉 \(message)")
            } else {
                print("❌ 支付失败:\(message)")
            }
        }
    }
}
  1. 外界调用
let order = Order(paymentStrategy: AlipayStrategy())

order.checkout(amount: 99.9)
// 输出:支付宝支付...

// 用户中途切换支付方式
order.changePaymentMethod(to: ApplePayStrategy())
order.checkout(amount: 199.0)
// 输出:Apple Pay...

输入验证示例

protocol ValidationStrategy {
    func isValid(_ input: String) -> Bool
    var errorMessage: String { get }
}

class EmailValidation: ValidationStrategy {
    var errorMessage = "请输入正确的邮箱地址"
    func isValid(_ input: String) -> Bool {
        let regex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
        return NSPredicate(format: "SELF MATCHES %@", regex).evaluate(with: input)
    }
}

class PasswordValidation: ValidationStrategy {
    var errorMessage = "密码至少8位,包含字母和数字"
    func isValid(_ input: String) -> Bool {
        return input.count >= 8 && input.range(of: "[A-Za-z]", options: .regularExpression) != nil
    }
}

// 表单验证器(Context)
class FormValidator {
    private var strategy: ValidationStrategy
    
    init(strategy: ValidationStrategy) {
        self.strategy = strategy
    }
    
    func validate(_ text: String) -> String? {
        return strategy.isValid(text) ? nil : strategy.errorMessage
    }
}

总结

在 Swift 开发中,策略模式几乎是“协议 + 运行时切换” 的最佳实践之一。它让你的代码更加灵活、可测试、可扩展,尤其适合那些“行为/算法经常变化”的场景(支付、验证、排序、AI、日志等)。 如果你在实际项目中遇到“一个类里面有大量 if-else 判断不同行为”的情况,强烈建议立刻重构为策略模式,代码会瞬间清晰很多!