【问题标题】:String construction using OOP and Proxy pattern使用 OOP 和代理模式构建字符串
【发布时间】:2011-12-10 22:45:23
【问题描述】:

我发现 SQLAlchemy 构造查询字符串的方式非常有趣,例如:

(Session.query(model.User)
        .filter(model.User.age > 18)
        .order_by(model.User.age)
        .all())

据我所知,那里应用了某种代理模式。在我的小项目中,我需要使用 OOP 方法进行类似的字符串构造。所以,我试图重构这种行为。

首先,某种对象,许多相似对象之一:

class SomeObject(object):
    items = None

    def __init__(self):
        self.items = []

    def __call__(self):
        return ' '.join(self.items) if self.items is not None else ''

    def a(self):
        self.items.append('a')
        return self

    def b(self):
        self.items.append('b')
        return self

这个对象的所有方法都返回self,所以我可以按任意顺序和无限次调用它们。

其次,代理对象,如果不是 perform 方法,它将调用主体的方法,该方法调用对象来查看结果字符串。

import operator

class Proxy(object):
    def __init__(self, some_object):
        self.some_object = some_object

    def __getattr__(self, name):
        self.method = operator.methodcaller(name)
        return self

    def __call__(self, *args, **kw):
        self.some_object = self.method(self.some_object, *args, **kw)
        return self

    def perform(self):
        return self.some_object()

最后:

>>> obj = SomeObject()
>>> p = Proxy(obj)
>>> print p.a().a().b().perform()
a a b

你对这个实现有什么看法?有没有更好的方法来制作所需数量的类,以使这样的字符串具有相同的语法

PS:对不起,我的英语不是我的主要语言。

【问题讨论】:

  • 为什么不看看 SQLAlchemy 代码,看看他们是如何做到的?

标签: python oop design-patterns sqlalchemy proxy-pattern


【解决方案1】:

实际上,您看到的不是代理模式,而是builder pattern,是的,恕我直言,您的实现是经典的(使用Fluent interface 模式)。

【讨论】:

  • 严格来说这不是建造者模式。尽管在我们这个时代,这样称呼它是一个常见的错误。这是“内部 DSL”或“流畅编程”的一个例子,后面的术语是使用最广泛的一个。 (构建器模式是关于构建对象图,您希望将构建算法 - 主管 - 与具体创建的对象分开,例如标题,摘要,索引,文档中的第 1 章,第 2 章,可以是PDF 文档或 HTML 文档等)
  • @AngelO'Sphere:感谢您的详细解释,我不知道这两种模式(构建器与流利的编​​程)之间存在差异,但我有一个问题:是否流利的编程(接口)是实现构建器模式的常用方法,所以在这种情况下,我们可以说查询是使用实现流利接口的构建器模式构建的?再次感谢您提供的额外知识:)
  • 如果我没记错的话,在最初的 GOF 书中,建造者们并不流利。然而,我总是使他们流利。从另一个方向回答您的问题:并非所有流利的“DSL”都与构建有关。例如。 FEST 框架使用流畅的 API 进行 UI 驱动的自动测试(自动鼠标点击等)
【解决方案2】:

我不知道 SQLAlchemy 是做什么的,但我会通过让 Session.query() 方法返回一个带有 filter()order_by()all() 等方法的 Query 对象来实现接口。这些中的每一个方法只返回一个新的Query 对象,并考虑到应用的更改。这允许像您的第一个示例中那样进行方法链接。

您自己的代码示例有很多问题。一个例子

obj = SomeObject()
p = Proxy(obj)
a = p.a
b = p.b
print a().perform()  # prints b

【讨论】:

    猜你喜欢
    • 2013-02-01
    • 2013-09-04
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多