Построение строки с использованием шаблона ООП и прокси - PullRequest
4 голосов
/ 19 октября 2011

Мне очень интересно, как SQLAlchemy строит строки запросов, например:

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

Насколько я могу видеть, там применен какой-то Прокси-шаблон .В моем небольшом проекте мне нужно сделать похожую струнную конструкцию, используя подход ООП.Итак, я попытался восстановить это поведение.

Во-первых, какой-то объект, один из множества похожих объектов:

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 поэтому я могу вызывать их в любом порядке и неограниченное количество раз.

Во-вторых, прокси-объект, который будет вызывать методы субъекта, если это не метод execute , который вызывает объект для просмотрарезультирующая строка.

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: Извините за мой английский, это не мой основной язык.

Ответы [ 2 ]

3 голосов
/ 19 октября 2011

На самом деле вы смотрите не на прокси-шаблон, а на шаблон , и да, ваша реализация IMHO классическая (с использованием шаблона Fluent interface ).

1 голос
/ 19 октября 2011

Я не знаю, что делает SQLAlchemy, но я бы реализовал интерфейс с помощью метода Session.query(), возвращающего объект Query с такими методами, как filter(), order_by(), all() и т. Д. Каждый из нихMethods просто возвращает новый объект Query с учетом примененных изменений.Это позволяет создавать цепочки методов, как в первом примере.

В вашем примере кода есть множество проблем.Один пример

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