一、命令设计模式简介
1.命令模式是一种行为设计模式,它利用对象之间的交互实现更强大的功能。(行为模式侧重于对象的响应性)
2.命令模式对象用于封装完成一项操作是或在出发一个事件时所需的全部信息。信息包括:方法名称、拥有方法的对象,方法参数的值。
二、了解命令设计模式
1.UML图
1.1 Command:声明借口操作
1.2 ConcreteCommand:将一个Receiver对象和一个操作绑定在一起
1.3 Client:创建ConcreteCommand对象病设定其接收者
1.4 Invoker:要求该ConcreteCommand执行这个请求
1.5 Receiver:知道如何实施与执行一个请求相关的操作
2.demo
# -*- coding: utf8 -*-
from abc import ABCMeta,abstractmethod
# 声明基类
class Command():
def __init__(self,recv):
self.recv = recv
def execute(self):
pass
# 接收对象和执行操作绑定
class ConcreteCommand(Command):
def __init__(self,recv):
self.recv = recv
def execute(self):
self.recv.action()
# 接收对象
class Receiver:
def action(self):
print ("Receiver Action")
# 执行请求
class Invoker:
def command(self, cmd):
self.cmd = cmd
def execute(self):
self.cmd.execute()
if __name__ == "__main__":
recv = Receiver()
cmd = ConcreteCommand(recv)
invoker = Invoker()
invoker.command(cmd)
invoker.execute()
三、实现现实世界中命令模式
# -*- coding: UTF-8 -*-
from abc import ABCMeta, abstractmethod
# 订单基类(Command)
class Order():
@abstractmethod
def execute(self):
pass
# 购买股票的订单(ConcreteCommand)
class BuyStockOrder(Order):
def __init__(self,stock):
self.stock = stock
# 执行买的操作
def execute(self):
self.stock.buy()
# 卖股票的借口(ConcreteCommand)
class SellStockOrder(Order):
def __init__(self, stock):
self.stock = stock
def execute(self):
self.stock.sell()
# 股票交易
class StockTrade:
def buy(self):
print ("You will buy stocks")
def sell(self):
print ("You will sell stocks")
# 代理(invoker)
class Agent:
def __init__(self):
self.__orderQueue = []
def placeOrder(self, order):
self.__orderQueue.append(order)
order.execute()
if __name__ == '__main__':
# Client
stock = StockTrade()
buyStock = BuyStockOrder(stock)
sellStock = SellStockOrder(stock)
# Invoker
agent = Agent()
agent.placeOrder(buyStock)
agent.placeOrder(sellStock)
四、命令模式的优缺点
1.优点
1.1 将调用操作的类与知道如何执行该操作的对象解耦。
1.2 提供队列系统后,可以创建一系列命令
1.3 添加新命令更加容易,并且无需更改现有代码
1.4 可以使用命令模式来定义回滚系统,例如,在向导示例中,我们可以编写一个回滚方法。
2.缺点
2.1 为了实现目标,需要大量的类和对象进行协作。应用程序开发人员为了正确开发这些类,需要加倍小心。
2.2 每个单独的命令都是一个ConcreteCommand类,从而增加了需要实现好维护的类的数量。
五、常见问答
1.命令模式中是否可以不实现ConcreteCommand和Receiver?
是的,可以。许多软件应用程序也是通过这种方式来使用命令模式的。这里唯一要注意的是调用者和接收者之间的交互。如果接收器未被定义的话,则去耦程度就会下降;另外,参数化命令的优势也就不复存在了。
2.我使用什么数据结构来实现Invoker对象中的队列机制?
在本章的股票交易所示例中,我们使用一个列表来实现队列。但是,命令模式还可以使用一个堆栈来实现队列机制,这在开发具有重做或回滚功能的时候非常有帮助。
本系列项目代码地址:Python-design-pattern