1. 简介
命令模式是一种行为设计模式,它允许将请求或操作封装成一个独立的对象,从而使得请求的发送者和接收者解耦。在命令模式中,命令对象包含了执行特定操作所需的所有信息,包括执行操作的方法以及操作的参数。
2. 命令模式的结构
2.1 模式结构
命令模式主要包含以下5个实体:
-
命令(Command) :命令是一个接口或抽象类,定义了执行特定操作的方法。
-
具体命令(Concrete Command) :具体命令是命令接口的具体实现,它包含了执行特定操作的具体逻辑和参数。
-
接收者(Receiver) :接收者是真正执行操作的对象,它知道如何执行具体的命令。
-
调用者/请求者(Invoker) :调用者是负责向命令对象发送请求的对象,它只知道如何调用命令对象,而不需要知道命令的具体实现细节。
-
客户端(Client) :客户端创建具体的命令对象,并将其与接收者对象关联起来,然后将命令对象传递给调用者对象。
2.2 UML图例
classDiagram
class Client {
+client()
}
class Invoker {
-commands: List[Command]
+addCommand(cmd: Command)
+executeCommand(args: Any)
}
class Command {
<<interface>>
+execute(args: Any)
}
class ConcreteCommand {
-receiver: Receiver
+execute(args: Any)
}
class Receiver {
+execute(args: Any)
}
Command <|.. ConcreteCommand
ConcreteCommand o-- Receiver
Invoker o-- Command
Client <.. Invoker
Client <.. Receiver
Client <.. ConcreteCommand
3. 命令模式的优缺点以及使用场景
命令模式在需要将请求封装成对象、支持撤销和重做、设计命令队列等情况下,都是一个有效的设计模式。
- 撤销操作: 需要支持撤销操作,命令模式可以存储历史命令,轻松实现撤销功能。
- 队列请求: 命令模式可以将请求排队,形成一个命令队列,依次执行命令。
- 可扩展性: 可以很容易地添加新的命令类和接收者类,而不影响现有的代码。新增命令不需要修改现有代码,符合开闭原则。
但是对于每个命令,都会有一个具体命令类,这可能导致类的数量急剧增加,增加了系统的复杂性。
4. 示例:【设计模式专题之命令模式】15-自助点餐机
"""
【设计模式专题之命令模式】15-自助点餐机
时间限制:1.000S 空间限制:256MB
题目描述
小明去奶茶店买奶茶,他可以通过在自助点餐机上来点不同的饮品,请你使用命令模式设计一个程序,模拟这个自助点餐系统的功能。
输入描述
第一行是一个整数 n(1 ≤ n ≤ 100),表示点单的数量。
接下来的 n 行,每行包含一个字符串,表示点餐的饮品名称。
输出描述
输出执行完所有点单后的制作情况,每行输出一种饮品的制作情况。如果制作完成,输出 "XXX is ready!",其中 XXX 表示饮品名称。
输入示例
4
MilkTea
Coffee
Cola
MilkTea
输出示例
MilkTea is ready!
Coffee is ready!
Cola is ready!
MilkTea is ready!
"""
from abc import ABC, abstractmethod
from typing import List
class DrinkMaker:
def make(self, drinkName: str):
print(f"{drinkName} is ready!")
class Order(ABC):
@abstractmethod
def place(self):
raise NotImplemented
class DrinkOrder(Order):
def __init__(self, drinkName: str, drinkMaker: DrinkMaker):
self.drinkName = drinkName
self.drinkMaker = drinkMaker
def place(self):
self.drinkMaker.make(self.drinkName)
class SelfOrderingMachine:
def __init__(self):
self.orders: List[Order] = []
def addOrder(self, order: Order):
self.orders.append(order)
def placeOrders(self):
for order in self.orders:
order.place()
def client():
maker = DrinkMaker()
machine = SelfOrderingMachine()
n = int(input())
for _ in range(n):
drinkName = input()
order = DrinkOrder(drinkName, maker)
machine.addOrder(order)
machine.placeOrders()
if __name__ == "__main__":
client()