Общий шаблон команды и шаблон диспетчера команд в 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()
Возможно, я ошибаюсь, но похоже, что это две разные концепции, которые случайно имеют похожие имена.
Мне что-то не хватает?
Ответы
Ответ 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()
и т.д.