python 命令模式

命令模式即对命令的封装, 将一系列操作封装至一个命令类中, 只需要调用一个对外公开的 execute 方法即可完成所有操作.

更进一步, 我们可以抽象出调用者, 命令和接收者三个对象.
整个流程为:

  1. 调用者持有一个命令对象.
  2. 调用者执行操作时实际是使用命令的 execute方法
  3. 命令的 execute 方法调用接收者实际执行的方法.

举例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from abc import ABC, abstractmethod

class Receiver:
"""命令接收者, 真正执行命令的地方
"""
def start(self):
print('at operation start')

def stop(self):
print('at operation stop')


class Command(ABC):
"""命令基类, 定义 execute 方法"""
@abstractmethod
def execute(self):
pass


class StartCommand(Command):
"""命令子类, 用一个接收者初始化并实现 execute 方法"""
def __init__(self, receiver):
self.receiver = receiver

def execute(self):
self.receiver.start()


class StopCommand(Command):

def __init__(self, receiver):
self.receiver = receiver

def execute(self):
self.receiver.stop()


class Operator:
"""命令调用者, 用一个命令初始化"""
def __init__(self, command):
self.command = command

def do(self):
# 执行操作时调用统一的 command.execute 方法
self.command.execute()

测试:

1
2
3
4
5
6
7
8
9
>>> rcv = Receiver()
>>> cmd1 = StartCommand(rcv)
>>> cmd2 = StopCommand(rcv)
>>> client = Operator(cmd1)
>>> client.do()
at operation start
>>> client.command = cmd2
>>> client.do()
at operation stop

以上是完全面向对象的方法, 但在 python 中函数作为一等公民, 完全可以使用 Command 类的
特殊方法 __call__ 来对 Command 和 Operator 进行简化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class StartCommand:

def __init__(self, receiver):
self.receiver = receiver

def __call__(self):
# 不需要继承基类, 遵循对此特殊方法的调用规定即可
self.receiver.start()

class StopCommand:

def __init__(self, receiver):
self.receiver = receiver

def __call__(self):
self.receiver.stop()


class Operator:
"""命令调用者, 用一个命令初始化"""
def __init__(self, command):
self.command = command

def do(self):
# 执行操作时直接调用即可
self.command()

测试代码不需要修改,行为也完全一致, 但代码得到了简化.