Подтвердить что ты не робот

Общий шаблон команды и шаблон диспетчера команд в Python

Я искал реализацию шаблона Command в Python... (Согласно Wikipedia,

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

)

Единственное, что я нашел, это Command Dispatch pattern:

class Dispatcher:

    def do_get(self): ...

    def do_put(self): ...

    def error(self): ...

    def dispatch(self, command):
        mname = 'do_' + command
        if hasattr(self, mname):
            method = getattr(self, mname)
            method()
        else:
            self.error()

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

Мне что-то не хватает?

4b9b3361

Ответ 1

Простейший командный шаблон уже встроен в Python, просто используйте вызываемый:

def greet(who):
    print "Hello %s" % who

greet_command = lambda: greet("World")
# pass the callable around, and invoke it later
greet_command()

Шаблон команды как объектно-ориентированный шаблон проектирования имеет больше смысла, если ваши команды должны иметь возможность делать больше, чем просто вызывать. Обычная usecase - это когда вам нужно отменить/повторить свои действия. Тогда класс команды - хороший способ связать действия вперед и назад. Например:

class MoveFileCommand(object):
    def __init__(self, src, dest):
        self.src = src
        self.dest = dest
        os.rename(self.src, self.dest)
    def undo(self):
        os.rename(self.dest, self.src)

undo_stack = []
undo_stack.append(MoveFileCommand('foo.txt', 'bar.txt'))
undo_stack.append(MoveFileCommand('bar.txt', 'baz.txt'))
# foo.txt is now renamed to baz.txt
undo_stack.pop().undo() # Now it bar.txt
undo_stack.pop().undo() # and back to foo.txt

Ответ 2

Сделал поиск и нашел это. Кажется, что он выполняет задачу инкапсуляции действия.

def demo(a,b,c):
    print 'a:',a
    print 'b:',b
    print 'c:',c

class Command:
    def __init__(self, cmd, *args):
        self._cmd=cmd
        self._args=args

    def __call__(self, *args):
       return apply(self._cmd, self._args+args)


cmd=Command(dir,__builtins__)
print cmd()

cmd=Command(demo,1,2)
cmd(3)

Ответ 3

Да, вы что-то пропустите: командный шаблон необходим только на языках, которые не имеют указателей на функции (или функционируют как объекты первого класса), например Java. В языках с функциями-как-объектами вы можете использовать сама функция; нет необходимости иметь отдельный объект команды (который затем должен иметь метод doit).

В примере, который вы могли бы процитировать, вызов getattr() дает вам "объект команды" (т.е. связанный метод); добавление скобок после того, как оно "вызывает" (т.е. вызывает) объект команды.

Ответ 4

Если я правильно помню банду из четырех, шаблон команды касается таких команд, как "Файл - Сохранить", а не таких команд, как "svn commit", что и подходит для вашего кода.

Мартин предполагает, что шаблон команды не нужен, потому что вместо него выполняются функции как объекты первого класса, но шаблон Command более богачен, чем просто doit(), имея, например, также undo(), is_enabled() и т.д.