策略模式:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
现在我们来定义一个计算器,加减乘除四个功能:
import UIKit
protocol StrategyProtocol {
func calculation(a: Double, b: Double) -> Double
}
//加
class SumStrategy: StrategyProtocol {
func calculation(a: Double, b: Double) -> Double {
return a + b
}
}
//减
class ReduceStrategy: StrategyProtocol {
func calculation(a: Double, b: Double) -> Double {
return a - b
}
}
//乘
class MultiplyStrategy: StrategyProtocol {
func calculation(a: Double, b: Double) -> Double {
return a * b
}
}
//除
class DivideStrategy: StrategyProtocol {
func calculation(a: Double, b: Double) -> Double {
return a / b
}
}
然后我们来个管理类,来执行这些算法,并且可以在外部切换算法:
import UIKit
class StrategyContext: NSObject {
var strategy: StrategyProtocol!
//返回自己,方便链式调用
func setStrategy(strategy: StrategyProtocol) -> StrategyContext{
self.strategy = strategy
return self
}
func executeStrategy(a: Double, b: Double) -> Double {
return self.strategy.calculation(a: a, b: b)
}
}
最后在调用的时候,我们需要知道自己想要的策略算法,传递给管理类,这样才能得到计算结果:
let context = StrategyContext()
let result1 = context.setStrategy(strategy: SumStrategy()).executeStrategy(a: 20, b: 30)
print(result1)
let result2 = context.setStrategy(strategy: ReduceStrategy()).executeStrategy(a: 20, b: 30)
print(result2)
let result3 = context.setStrategy(strategy: MultiplyStrategy()).executeStrategy(a: 20, b: 30)
print(result3)
let result4 = context.setStrategy(strategy: DivideStrategy()).executeStrategy(a: 20, b: 30)
print(result4)
打印结果:
50.0
-10.0
600.0
0.6666666666666666
如此简单的功能,设计的这么复杂,有什么好处呢?假如这里我们要加上一个取模的算法,只需再写一个类,实现策略接口,就可以在外部直接调用了。
再举一个例子:
高德地图查询某个地点时,出来的路线有很多种,骑车、驾车、步行、公交等各种出行策略,每种策略又有好几条路线,如果全部都耦合到一个类里,此类将会非常复杂,这时候我们可以定义一个策略接口,由策略类分别执行路线规划,然后定义一个管理类Context来切换不同的策略,当用户点击选择不同的出行方式时,由Context来执行出行策略,给出路线规划。
上次面试遇到一个问题,一个商品可能会有很多优惠方式,优惠券啊,打折啊,满减啊,买五送一啊,还可能会有各种优惠方式叠加,这个时候如果写在一个类里,通过if else来区分,这个类很快就会不能维护,这个时候就可以用策略模式,不论后期添加什么活动,都可以通过增加一个类来实现,符合开闭原则。