标签搜索

策略模式

Pop.Kite
2022-01-23 / 0 评论 / 118 阅读 / 正在检测是否收录...

假使我们正在做一个语音助手,我们的语音助手能够查询天气,播放音乐,拨打电话...我们有一个Manager类用于管理天气、音乐、电话模块。使用流水线的开发是当传递来的是天气的代码,我们可以用if...else或者switch...case来判断它应该分发到哪个模块。但是如果业务增多,我们就需要不停的添加判断分支,会造成代码的冗余,不符合设计原则的开闭原则,此时我们可以使用策略模式。

策略模式的主要优点如下。
1. 多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句,如 if...else 语句、switch...case 语句。
2. 策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。
3. 策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。
4. 策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。
5. 策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。

其主要缺点如下。
1. 客户端和服务端需要对策略类有一个共识,以便适时选择恰当的算法类。
2. 策略模式造成很多的策略类,增加维护难度。
  1. 我们将各模块业务抽象成一个BaseModel接口,含有一个方法execute()用于执行逻辑:
//抽象策略
interface BaseModel{
    fun execute()
}
  1. 各模块继承该接口,并在实现execute()方法用于处理自己的逻辑:
//具体策略
calss WeatherModel : BaseModel{
   override fun execute(){
       println("天气模块处理")
   }
}

calss MediaModel : BaseModel{
   override fun execute(){
       println("媒体模块处理")
   }
}

calss CallModel : BaseModel{
   override fun execute(){
       println("通话模块处理")
   }
}
  1. 我们使用一个Manager单例对象用于处理对应的消息应该进入哪一个策略:
//策略处理
object Manager{
    var model: BaseModel? = null
    fun execute(){
        if(model.initialized()){
            model.execute()
        } else {
            println("model not init!")
        }
    }

   fun <T> T.initialized() :Boolean{
        return this != null
    }
}
  1. 传递指定的对象到管理对象中,管理对象就可以执行对应的方法了,而不需我们手动判断
object Main{
    @JvmStatic
    fun main(args: Array<String>) {
        Manager.model = WeatherModel()
        StrategyContext.strategyMethod()
    }
}
//输出了 天气模块处理
0

评论 (0)

取消