策略(Strategy)模式的定义:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。
在现实生活中常常遇到实现某种目标存在多种策略可供选择的情况,例如,出行旅游可以乘坐飞机、乘坐火车、骑自行车或自己开私家车等,超市促销可以采用打折、送商品、送积分等方法。
在软件开发中也常常遇到类似的情况,当实现某一个功能存在多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能,如数据排序策略有冒泡排序、选择排序、插入排序、二叉树排序等。
如果使用多重条件转移语句实现(即硬编码),不但使条件语句变得很复杂,而且增加、删除或更换算法要修改原代码,不易维护,违背开闭原则。如果采用策略模式就能很好解决该问题。
- //用策略模式实现计算器加减乘除
- enum class OperationStr {
- Plus,
- Subtraction,
- Multiplication,
- Division
- }
-
- interface Operation {
- fun calculation(var1: Double, var2: Double): Double
- }
-
- class PlusOperation : Operation {
- override fun calculation(var1: Double, var2: Double) = var1 + var2
- }
-
- class SubtractionOperation : Operation {
- override fun calculation(var1: Double, var2: Double) =
- (var1 - var2).takeIf { var1 - var2 >= 0 } ?: throw IllegalArgumentException()
- }
-
- class MultiplicationOperation : Operation {
- override fun calculation(var1: Double, var2: Double) = var1 * var2
- }
-
- class DivisionOperation : Operation {
- override fun calculation(var1: Double, var2: Double) =
- if (var1 != 0.0) var1 / var2 else throw IllegalArgumentException()
- }
-
- //由初始化来决定具体要执行哪一种策略
- class OperationContext(private val operation: Operation) {
- fun executeStrategy(num: Double, num2: Double) = operation.calculation(num, num2)
- }
-
- //算法控制器
- class Calculator {
-
- fun selectOperation(operation : OperationStr) : OperationContext {
- val selectedOperation = when (operation) {
- OperationStr.Plus -> PlusOperation()
- OperationStr.Subtraction -> SubtractionOperation()
- OperationStr.Multiplication -> MultiplicationOperation()
- OperationStr.Division -> DivisionOperation()
- }
-
- return OperationContext(selectedOperation)
- }
-
- }
-
- fun main() {
- //假设使用计算器是用的数
- val num1 = 1.0
- val num2 = 1.0
- val calculator : Calculator = Calculator()
- //选择加法
- println(calculator.selectOperation(OperationStr.Plus).executeStrategy(num1, num2))
- //选择了减法
- println(calculator.selectOperation(OperationStr.Subtraction).executeStrategy(num1, num2))
- //选择了乘法
- println(calculator.selectOperation(OperationStr.Multiplication).executeStrategy(num1, num2))
- //选择了除法
- println(calculator.selectOperation(OperationStr.Division).executeStrategy(num1, num2))
- }