思想
把“算法/行为”从“使用它的类”中抽离出来,让客户端在运行时动态切换策略,而不需要修改 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()
...
}
}
策略模式封装
- 抽象策略协议
protocol PaymentStrategy {
func pay(amount: Double, completion: @escaping (Bool, String) -> Void)
}
- 具体策略实现
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 支付成功")
}
}
- 上下文(订单支付类)
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)")
}
}
}
}
- 外界调用
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 判断不同行为”的情况,强烈建议立刻重构为策略模式,代码会瞬间清晰很多!