starting
比较先从一个最简单的模式,策略模式说起。
策略模式是指把策略的实现放到具体的类中,而不是直接写死到同一块if...else
上。
在oop的实现中,策略被抽象成一个接口,也就是说这些策略类都要实现同一个策略接口。这样的好处是,使用策略和策略本身是解耦的,而且策略之间也是彼此独立的封装。新的策略可以随意被替换进来,而使用者“几乎”不用改什么代码。
在使用策略的类中,策略类作为使用策略类的一个属性,使用类直接调用策略类的execute方法,而这个策略到底被设置成了什么,此时此刻使用者并不知道,也并不需要知道。
我一直在想策略模式中,为啥要把策略做成一个属性,而非直接当成一个变量去使用,我想是因为属性能提供更多的功能吧,包括装饰器或者像spring的bean一样可以被配置。
java实现
// 首先你要有一个策略接口
1 | public interface ICompositor{ |
可以看出,策略模式是一种很基础的,用到接口特性的模式。
python实现
在python中首先你完全没必要去实现接口,因为python的“鸭子类型”,你只要有这个方法就行了。
而且一般策略就是一个函数,而python中函数也是个对象,所以你连一个类都不用去定义。
1 |
|
其它思路
就算没有oop的时候,策略模式的设计思路我在之前也见到过。
比如C语言标准库的qsort函数
1 | void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *)); |
具体的比较规则,是使用函数指针作为参数的,需要传递一个策略函数。这种函数被称为钩子函数,不只是c语言,其它语言的排序函数也大同小异,都是可以选择排序的规则策略。
还要说明的一点是,策略模式只是把策略的具体实现,通过接口实现的方式,推迟到子类中去了,但是并没有解决,什么时候去抉择用那种策略,也就是说,很可能你的外层,在选择策略的时候,还是再用if else,或者case,或者一个表驱动。比如上面的例子,你最终可能会这样创建:
1 | if xxx: |
说这个的目的,原因就是很多设计模式狂热者,喜欢把所有的ifelse
,都用设计模式包装了,而不是考虑设计模式到底解决了一个什么问题。