Pulpcode

捕获,搅碎,拼接,吞咽

0%

从python到java之设计模式策略模式

starting

比较先从一个最简单的模式,策略模式说起。

策略模式是指把策略的实现放到具体的类中,而不是直接写死到同一块if...else上。

在oop的实现中,策略被抽象成一个接口,也就是说这些策略类都要实现同一个策略接口。这样的好处是,使用策略和策略本身是解耦的,而且策略之间也是彼此独立的封装。新的策略可以随意被替换进来,而使用者“几乎”不用改什么代码。

在使用策略的类中,策略类作为使用策略类的一个属性,使用类直接调用策略类的execute方法,而这个策略到底被设置成了什么,此时此刻使用者并不知道,也并不需要知道。

我一直在想策略模式中,为啥要把策略做成一个属性,而非直接当成一个变量去使用,我想是因为属性能提供更多的功能吧,包括装饰器或者像spring的bean一样可以被配置。

java实现

// 首先你要有一个策略接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public interface ICompositor{
public void compose();
}

// 你的所有策略都要继承于此接口

public class Compositor1 implements ICompositor{

@Override
public void compose(){

}
}

public class Compositor2 implements ICompositor{

@Override
public void compose(){

}
}


// 最后你可以在类里这样使用
public class Composition{

private ICompositor iCompositor;

public Composition(ICompositor iCompositor){
this.iCompositor = iCompositor;
}

public void Repair(){
iCompositor.compose();
}
}

可以看出,策略模式是一种很基础的,用到接口特性的模式。

python实现

在python中首先你完全没必要去实现接口,因为python的“鸭子类型”,你只要有这个方法就行了。
而且一般策略就是一个函数,而python中函数也是个对象,所以你连一个类都不用去定义。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

def compositor1():
xxxx
....

def compositor2():
xxxx
....



class Composition(object):

def __init__(self, compositor):
self.compositor = compositor

def repair(self):
self.compositor()

其它思路

就算没有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
2
3
4
if xxx:
Composition(compositor1)
else:
Composition(compositor2)

说这个的目的,原因就是很多设计模式狂热者,喜欢把所有的ifelse,都用设计模式包装了,而不是考虑设计模式到底解决了一个什么问题。