策略模式简介
维基百科定义:策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法
实现原理,如下图
个人理解
案例介绍
首先,我们忘掉策略模式这个概念。在策略模式出来之前,先看一个案例:
一个班级有2个学生,开学的时候,老师要求每个人都做自我介绍,说下自己的名字和技能,程序的伪代码如下:
现在学校举行了一场数学竞赛,需要派两个人去参加比赛,张三和李四都去了。比赛有规定,不同的题目可以由不同的选手回答。那么这时候就需要分析张三和李四各自的优势。张三心算比较快,但是不能太复杂。李四口算比较慢,但是可以比较复杂。程序的伪代码如下:
总结上述案例得到:
首先要有触发条件:在没有条件的情况下,就没有所谓的选择。所以首要条件就是要有触发条件,有了条件之后,其次就是通过条件,我们得选取一个最适合的方案,选了好了之后,就开始去具体的执行。其实这个choose 就是最简单策略的选取
看了这个例子,伪代码中最容易腐败的位置就是在选择上,目前 影响选人的维度只有题目的复杂度,如果还有其他更多的维度,或者是有更多的候选人进行选择。那么这段代码就会非常的复杂,那怎么办呢? 怎么办之前我们先来看一张图
第一种方式:
策略在业务方去选取,执行方不管。这样就会出现demo中说的问题,执行方只管处理具体的执行,至于你业务上要怎么执行,你自己决定
第二种方式:
策略在执行方去选取就,执行方来管理,不会出现demo 中的问题,执行方只需要将条件告诉我,执行方来决定怎么执行。
上述两种方式,大家是不是觉得,不都一样吗?
我来解(狡)释(辩)下
用最简单的语言来解释下:假设,业务方和策略执行两个同学,那么你们就会遇到这个问题,到底谁来选取策略来执行的问题。毕竟能少些一点代码就少写一点!
当然又有同学要开始问(喷)了,日常开发,很多时候都是我一个人既要写业务代码,又要写策略那块的代码,都是我在写,是不是就一样了?
编不下去了,确实如此,这段代码在哪不重要,重要的是这个问题始终存在。
普通的策略模式也会遇上同样的问题,当策略很多的时候,choose里面的代码就会很多,很丑陋,最终可能还是会写成很多的if else。
最后就蜕变成了,为了设计模式而设计模式了
回头看下策略模式的设计
这里只告诉了我们在遇到这种多种策略的情况下如何用优雅的方式去解决,但是我new 进去的策略的选取又改怎么解决呢? 貌似就变成了死循环,我用策略模式 引发了另外一个 策略问题。
当然他的好处就是,复杂的地方被收口了,那一个地方复杂就行了,业务方和策略执行方都不需要管。
遇到问题解决问题
现在最大的问题就是 这个策略选取的部分比较棘手,谁都不想要~ 那么有没有一种比较好的方式去解决呢? 举个栗子,比如让策略和执行器做个自动绑定,业务方只需要丢进去条件,至于你怎么执行,系统可以自动寻找。执行器这边也还是只需要负责写好执行就好
策略模式的自动绑定
执行器首先得把自己的能力告诉上下文,我能处理什么样的参数。
业务方呢,只需要把参数告诉上下文,得到一个指定的执行器,最终开始执行即可。
其实这里和之前的策略模式,仅仅只多了一个执行器把能处理什么参数的能力暴露出来!而不是让业务方去做手动判定。
Spring 模式下的自动绑定
现在方案很清晰,如何让执行器上报自己的参数处理能力,下面提供几种不同的绑定方式提供参考。
接口方法
在定义执行器接口的时候,增加check方法,将参数都丢进去,context每次执行的时候,便利所有的执行器,只要check返回true的,就代表我能处理
类似上图中的接口定义。context中就能实现每次自动寻找
注解方法
在对应的执行器上增加一个自定义注解,注解的内容就是我能处理的参数。context在初始化的时候,把所有带这个注解的执行器都找出来,初始化在Map里。
这样就能实现自动寻找
主动注册告知
定义好context,context暴露出注册能力,执行器在spring bean 初始化结束之后,自己注册到context里去,并告知能处理的参数值。
在spring下,这三种方式,都谈不上优雅,但是也都能解决策略模式的问题。我用的最多的还是接口方法 ,可能是相对来说比较简单,但是坏处就是入侵了业务代码,本来这不是他的事情。
结尾
if else 真的这么讨厌吗? 还是仅仅只是跟风? 无辜的swicth 躲在角落 瑟瑟发抖
spring中aop的策略模式代码
判定解析对象的类型,分析环境、资源、BeanFactory和类加载的处理策略
有没有发现,都是 if 。细心的大佬应该已经发现了,源码中有if,但是没有else。
对! 这就是精华,if else 很讨厌, if 并不讨厌 !
上述仅仅代表个人思考~ 不喜勿喷