首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >元器件设计问题

元器件设计问题
EN

Stack Overflow用户
提问于 2009-07-10 02:11:05
回答 1查看 241关注 0票数 3

更新问题,见下面的

我要开始一个新项目,我想尝试基于组件的体系结构(我选择了PyProtocols)。这是一个显示和与实时图形交互的小程序。

我首先设计了用户输入组件:

  • IInputDevice -例如鼠标、键盘等.一个InputDevice可能有一个或多个输出通道:
    • IOutput -包含单个值的输出通道(例如MIDI滑块的值)
    • ISequenceOutput -一个包含一系列值的输出通道(例如,两个表示鼠标位置的整数)
    • IDictOutput -一个包含命名值的输出通道(例如,键盘的每个键的状态,由键盘符号索引)

现在,我想定义一些接口来过滤这些输出(平滑、抖动、倒转等等)。

我的第一种方法是创建一个InputFilter接口,它对连接到的每种输出通道都有不同的过滤方法。但是PyProtocols文档中的介绍清楚地指出,整个接口和适配器都是关于避免类型检查的!

因此,我猜想我的InputFilter接口应该如下所示:

  • IInputFilter -过滤器IOutput
  • ISequenceInputFilter -过滤器ISequenceOutput
  • IDictInputFilter -过滤器IDictOutput

然后,我可以在I*Ouptut接口中使用connect()方法,该方法可以神奇地调整我的过滤器,并使用适合于输出类型的方法。

我试着去实现它,它起作用了:

代码语言:javascript
复制
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

现在,我可以根据输出的类型调整我的过滤器:

代码语言:javascript
复制
filter = InvertInputFilter()
single_filter = IInputFilter(filter)           # noop
sequence_filter = ISequenceInputFilter(filter) # creates an InvertSequenceInputFilter instance

single_filter和sequence_filter具有正确的行为,并产生单一和序列数据类型。现在,如果我在同一个模型上定义了一个新的InputFilter类型,就会得到如下错误:

代码语言:javascript
复制
TypeError: ('Ambiguous adapter choice', <class 'InvertSequenceInputFilter'>, <class 'SomeOtherSequenceInputFilter'>, 1, 1)

我一定做错了什么,我的设计是否正确?或者我是不是错过了如何实现我的InputFilterS的要点?

更新2

我知道我在这里期待太多的魔力,适配器不键入它们正在调整的对象,只查看它们提供的接口,这对我来说现在听起来很正常(请记住,我对这些概念很陌生!)

因此,我提出了一个新的设计(剥离到最低限度,省略了dict接口):

代码语言:javascript
复制
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提供了专门的实现。现在,我可以将适配器从专用接口编写到通用接口:

代码语言:javascript
复制
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:

代码语言:javascript
复制
class InvertInputFilter(object):

    advise(
            instancesProvide=[
                    ISingleInputFilter, 
                    ISequenceInputFilter
                ]
        )

    def read_single(self):
        # Return single value inverted

    def read_sequence(self):
        # Return sequence of inverted values 

要将它与各种输出类型一起使用,我将这样做:

代码语言:javascript
复制
filter = InvertInputFilter()
single_filter = SingleInputFilterAsInputFilter(filter)
sequence_filter = SequenceInputFilterAsInputFilter(filter)

但是,同样地,同样的错误失败了,这一次是由InvertInputFilter定义直接触发的:

代码语言:javascript
复制
TypeError: ('Ambiguous adapter choice', <class 'SingleInputFilterAsInputFilter'>, <class 'SequenceInputFilterAsInputFilter'>, 2, 2)

(一旦我在类的instancesProvide子句中放置了一个接口,错误就会被删除)

更新3

在对峰值邮件列表进行了一些讨论之后,最后一个错误似乎是由于PyProtocols中的一个设计缺陷造成的,该漏洞在声明时会执行一些额外的检查。我用zope.interface重写了所有的东西,它运行得非常完美。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2009-07-10 06:21:25

我没有使用PyProtocols,只使用Zope组件体系结构,但是它们非常相似,以至于这些原则是相同的。

您的错误是,您有两个适配器可以适应相同的事情。你们两个都有一个平均滤波器和一个反演算滤波器。然后,当您请求筛选器时,两者都会被找到,并且您将得到“雄心勃勃的适配器”错误。

您可以通过使用不同的接口来处理这个问题,用于平均过滤器和反向过滤器,但是它变得越来越愚蠢了。在Zope组件体系结构中,通常使用命名适配器来处理这种情况。默认情况下,每个适配器都会获得一个名称。在这种情况下,您将给适配器名,如“平均”和“反转”,然后使用该名称查找它们,因此您知道是平均值还是反向筛选器。

对于更普遍的问题,如果设计是否合理,那就很难说了。有三种不同的输出和三种不同的过滤器似乎不是个好主意。也许您可以将序列和dict输出组合到单个值输出的组合中,这样每个输出值都会得到它自己的对象,因此可以独立地过滤它。这对我来说更有意义。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1107368

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档