更新的问题,请参见下面菜鸟组件设计问题
我开始一个新项目,我想与部件试验基础架构(我选择了PyProtocols)。这是一个显示和实时图形交互的小程序。
我开始通过设计用户输入组件:
- IInputDevice - 例如鼠标,键盘,等等的可的InputDevice具有一个或多个输出信道:
- IOutput - 包含单个值(例如,MIDI滑块的值)
- ISequenceOutput的输出通道 - 包含的值(例如2个整数表示鼠标位置)的序列
- IDictOutput输出信道 - 包含名为值的输出信道(例如在键盘的每个键,通过键盘符号索引的状态)
现在我想定义接口来过滤那些输出(平滑,抖动,反转等)。
我的第一种方法是创建一个InputFilter接口,它为每种输出通道连接了不同的过滤方法......但PyProtocols文档中的介绍清楚地表明,整个接口和适配器的事情是关于避免类型检查!
所以我的猜测是,我的输入过滤器的接口应该是这样的:
- IInputFilter - 过滤IOutput
- ISequenceInputFilter - 过滤ISequenceOutput
- IDictInputFilter - 过滤器IDictOutput
然后,我可以在I * Ouptut接口中有一个connect()方法,它可以神奇地调整我的过滤器并使用适合于输出类型的方法。
我试图实现这一点,这样的工作原理:
class InputFilter(object):
"""
Basic InputFilter implementation.
"""
advise(
instancesProvide=[IInputFilter],
)
def __init__(self):
self.parameters = {}
def connect(self, src):
self.src = src
def read(self):
return self.src.read()
class InvertInputFilter(InputFilter):
"""
A filter inverting single values.
"""
def read(self):
return -self.src.read()
class InvertSequenceInputFilter(InputFilter):
"""
A filter inverting sequences of values.
"""
advise(
instancesProvide=[ISequenceInputFilter],
asAdapterForProtocols=[IInputFilter],
)
def __init__(self, ob):
self.ob = ob
def read(self):
res = []
for value in self.src.read():
res.append(-value)
return res
现在,我可以在我的过滤器适应输出类型:
filter = InvertInputFilter()
single_filter = IInputFilter(filter) # noop
sequence_filter = ISequenceInputFilter(filter) # creates an InvertSequenceInputFilter instance
single_filter和sequence_filter有正确的行为和产生单个和序列数据类型。现在,如果我在同一个模型中定义一个新的输入过滤器的类型,我得到的错误是这样的:
TypeError: ('Ambiguous adapter choice', <class 'InvertSequenceInputFilter'>, <class 'SomeOtherSequenceInputFilter'>, 1, 1)
我必须做一些可怕的错误,是我设计的,即使正确吗?或者,我是否错过了如何实现我的InputFilterS?
更新2
我明白我期待有点太多魔力这里,适配器没有类型检查正在修改的对象,只是看他们提供的接口,它现在听起来正常的我(记住我是这些概念的新手!)。
于是我想出了一个新的设计(剥离到最低限度,并且省略了快译通接口):
class IInputFilter(Interface):
def read():
pass
def connect(src):
pass
class ISingleInputFilter(Interface):
def read_single():
pass
class ISequenceInputFilter(Interface):
def read_sequence():
pass
所以IInputFilter现在是一种通用的组件,即实际使用的一个,ISingleInputFilter和ISequenceInputFilter提供了专门的实现。现在,我可以写在专门的适配器通用接口:
class SingleInputFilterAsInputFilter(object):
advise(
instancesProvide=[IInputFilter],
asAdapterForProtocols=[ISingleInputFilter],
)
def __init__(self, ob):
self.read = ob.read_single
class SequenceInputFilterAsInputFilter(object):
advise(
instancesProvide=[IInputFilter],
asAdapterForProtocols=[ISequenceInputFilter],
)
def __init__(self, ob):
self.read = ob.read_sequence
现在,我写我的InvertInputFilter这样的:
class InvertInputFilter(object):
advise(
instancesProvide=[
ISingleInputFilter,
ISequenceInputFilter
]
)
def read_single(self):
# Return single value inverted
def read_sequence(self):
# Return sequence of inverted values
,并与各种输出类型使用它,我会做:
filter = InvertInputFilter()
single_filter = SingleInputFilterAsInputFilter(filter)
sequence_filter = SequenceInputFilterAsInputFilter(filter)
但是,再一次地,这种失败与同样的错误是一样的,这次它直接由InvertInputFilter定义触发:
TypeError: ('Ambiguous adapter choice', <class 'SingleInputFilterAsInputFilter'>, <class 'SequenceInputFilterAsInputFilter'>, 2, 2)
更新3
的PEAK邮件列表上的一些讨论后(只要我把只有一个接口在类的instancesProvide条款的错误在前看不见),似乎这最后一个错误是由于PyProtocols中的设计缺陷造成的,它在声明时会做一些额外的检查。我用zope.interface重写了所有内容,并且完美地工作。
谢谢,现在我更好地了解适配器如何工作。 指定的适配器在PyProtocols中不可用,如果我理解的很好,它们只是语法糖,并且它基本上与我的每个过滤器具有不同接口的情况基本相同(我希望能够在单独的插件中创建过滤器,无需创建新的界面或独特的名称)。 我不想做作文,因为它会产生类型检查,这正是我想要首先避免的。 – 2009-07-10 15:41:55