Python 设计模式——命令模式

命令模式是一种行为设计模式。可以用来实现比如安装软件时的安装向导功能,通常安装向导会通过多个步骤根据用户的选择了解用户的偏好。安装向导首先启动一个名为 Command 的对象,用于存储在向导的多个步骤中用户指定的选项。当用户在最后一个步骤中点击完成按钮时,Command 对象就会运行 execute() 方法,该方法会考察所有存储的选项并完成相应的安装过程。

UML

命令模式通常包含以下术语:

  • Command 对象了解 Receiver 对象的情况,并能调用其方法
  • 调用者(Invoker)方法的参数值存储在 Command 对象中
  • 调用者知道如何执行命令
  • 客户端(Client)用来创建 Command 对象并设置其接收者

命令模式的主要意图:

  • 将请求封装为对象
  • 可用不同的请求对客户端进行参数化
  • 允许将请求保存在队列中
  • 提供面向对象的回调

命令模式的适用场景:

  • 根据需要执行的操作对对象进行参数化
  • 将操作添加到队列并在不同地点执行请求
  • 创建一个结构根据较小的操作来完成高级操作

代码示例

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
46
47
48
49
50
51
52
from abc import ABCMeta, abstractmethod

class Order(metaclass=ABCMeta):

@abstractmethod
def execute(self):
pass


class BuyStockOrder(Order):
def __init__(self, stock):
self.stock = stock

def execute(self):
self.stock.buy()


class SellStockOrder(Order):
def __init__(self, stock):
self.stock = stock

def execute(self):
self.stock.sell()


class Agent:
def __init__(self):
self.__orderQueue = []

def placeOrder(self, order):
self.__orderQueue.append(order)
order.execute()


class StockTrade:
def buy(self):
print("You will buy stocks")

def sell(self):
print("You will sell stocks")


if __name__ == '__main__':
stock = StockTrade()
buyStock = BuyStockOrder(stock)
sellStock = SellStockOrder(stock)

agent = Agent()
agent.placeOrder(buyStock)
agent.placeOrder(sellStock)
# => You will buy stocks
# => You will sell stocks
  • Order 类 -> Command 对象
  • BuyStockOrder 和 SellStockOrder 类 -> ConcreteCommand 对象,为交易系统定义适当的操作
  • StockTrade 类 -> Receiver 对象,定义了多个方法(动作)可以被 ConcreteCommand 调用以买入或卖出股票
  • Agent 类 -> Invoker 对象,作为客户端和 StockTrade 的中介,执行客户下达的订单

命令模式的优点:

  • 将调用操作的类与知道如何执行该操作的类解耦
  • 借助队列系统,可以创建一系列命令
  • 添加新命令更加容易,无需更改现有代码
  • 可以使用命令模式定义回滚系统

命令模式的缺点:

  • 为了实现目标,需要大量的类和对象进行协作
  • 每个单独的命令都是一个 ConcreteCommand 类,增加了实现和维护的成本