Tuesday, July 3, 2007

Mixin 和 Plugin

mixin 是统称,我又区分为Mixin和Plugin两种。

Mixin 是增加新东西或与原有的东西合并。比如向一个类增加属性或方法。
Plugin 相当于一个回调函数的扩展,它的调用入口一定是存在于某个方法中。举例来说:

class A(Mixin):
__mixinname__ = 'a'

def __init__(self):
self.initmixin()
#code
self.callplugin('plugin1', args1, args2)
#code
obj = self.execplugin('plugin2', args1, args2, args3)

上面的代码是一个slot class的例子,其中self.callplugin()和self.execplugin()是对于两种不同的Plugin的调用点。

为什么有这个东西的想法就是,我可以使用Mixin的方式将__init__方法替换掉,但可能我的处理代码为了不影响以前的东西仍然要保存许多的原始代码,这样程序看上去很乱。比如,不使用Plugin的方式,类可能为:

class A:
def __init__(self):
code1
code2

这时我发现A需要修改,那么可能需要在code1和code2之间加入一些代码,不使用mixin技术,你一定是要么直接修改A的代码,要么从A派生,不管怎能么样,__init__的代码都会为:

def __init__(self):
code1
newcode
code2

这样code1和code2就需要保留。如果再需要在code1和code2之间加入代码,你又要做这样的工作,要么修改A,要么从A派生,然后保留以前的代码。而采用mixin技术,你只需要在code1与code2之间加入一个插入点,那么A类就基本上不需要修改了。新的代码就使用一个新的Plugin来实现,再增加新的代码就再写一个Plugin就行了。能过Mixin模块将其合成一个Plugin的链。

因为Plugin是处于代码中间的,因此叫这个名字,这与插件的工作方式是一样的。而callplugin和execplugin的调用就是Plugin的接口定义。第一个参数是这个plugin接口的名字,后面是它的参数。而定义Plugin方法时需要按调用接口来定义参数,如上面的plugin1有两个参数,它的某个Plugin定义为:

def myplugin1(a, b):
print a, b
Mixin.setPlugin('a', 'plugin1', myyplugin1)

这样就通过Mixin模块的setPlugin方法将myplugin1与__mixinname__为'a'的plugin调用点为'plugin1'的接口关联起来了。

在执行callplugin和execplugin时不需要传入slot class
的__mixinname__,因为自已知道在调用Plugin时使用哪个slot class的Plugins。

No comments: