更新问题,见下面的
我要开始一个新项目,我想尝试基于组件的体系结构(我选择了PyProtocols)。这是一个显示和与实时图形交互的小程序。
我首先设计了用户输入组件:
现在,我想定义一些接口来过滤这些输出(平滑、抖动、倒转等等)。
我的第一种方法是创建一个InputFilter接口,它对连接到的每种输出通道都有不同的过滤方法。但是PyProtocols文档中的介绍清楚地指出,整个接口和适配器都是关于避免类型检查的!
因此,我猜想我的InputFilter接口应该如下所示:
然后,我可以在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 instancesingle_filter和sequence_filter具有正确的行为,并产生单一和序列数据类型。现在,如果我在同一个模型上定义了一个新的InputFilter类型,就会得到如下错误:
TypeError: ('Ambiguous adapter choice', <class 'InvertSequenceInputFilter'>, <class 'SomeOtherSequenceInputFilter'>, 1, 1)我一定做错了什么,我的设计是否正确?或者我是不是错过了如何实现我的InputFilterS的要点?
更新2
我知道我在这里期待太多的魔力,适配器不键入它们正在调整的对象,只查看它们提供的接口,这对我来说现在听起来很正常(请记住,我对这些概念很陌生!)
因此,我提出了一个新的设计(剥离到最低限度,省略了dict接口):
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)(一旦我在类的instancesProvide子句中放置了一个接口,错误就会被删除)
更新3
在对峰值邮件列表进行了一些讨论之后,最后一个错误似乎是由于PyProtocols中的一个设计缺陷造成的,该漏洞在声明时会执行一些额外的检查。我用zope.interface重写了所有的东西,它运行得非常完美。
发布于 2009-07-10 06:21:25
我没有使用PyProtocols,只使用Zope组件体系结构,但是它们非常相似,以至于这些原则是相同的。
您的错误是,您有两个适配器可以适应相同的事情。你们两个都有一个平均滤波器和一个反演算滤波器。然后,当您请求筛选器时,两者都会被找到,并且您将得到“雄心勃勃的适配器”错误。
您可以通过使用不同的接口来处理这个问题,用于平均过滤器和反向过滤器,但是它变得越来越愚蠢了。在Zope组件体系结构中,通常使用命名适配器来处理这种情况。默认情况下,每个适配器都会获得一个名称。在这种情况下,您将给适配器名,如“平均”和“反转”,然后使用该名称查找它们,因此您知道是平均值还是反向筛选器。
对于更普遍的问题,如果设计是否合理,那就很难说了。有三种不同的输出和三种不同的过滤器似乎不是个好主意。也许您可以将序列和dict输出组合到单个值输出的组合中,这样每个输出值都会得到它自己的对象,因此可以独立地过滤它。这对我来说更有意义。
https://stackoverflow.com/questions/1107368
复制相似问题