# Python設計模式中命令模式怎么實現
## 什么是命令模式
命令模式(Command Pattern)是一種行為型設計模式,它將請求或操作封裝為一個對象,從而使你可以參數化客戶端與不同的請求、隊列或日志請求,并支持可撤銷的操作。
### 核心思想
- **解耦調用者與接收者**:調用操作的對象不需要知道如何實現操作
- **將請求封裝為對象**:每個命令都是一個獨立的對象,包含執行操作所需的所有信息
- **支持命令隊列**和**撤銷/重做**功能
## 命令模式的結構
### 主要角色
1. **Command(命令接口)**:聲明執行操作的接口
2. **ConcreteCommand(具體命令)**:
- 實現Command接口
- 綁定接收者與動作
3. **Invoker(調用者)**:要求命令執行請求
4. **Receiver(接收者)**:知道如何執行操作
5. **Client(客戶端)**:創建具體命令并設置接收者
```python
from abc import ABC, abstractmethod
# Command接口
class Command(ABC):
@abstractmethod
def execute(self):
pass
# Receiver
class Light:
def turn_on(self):
print("Light is ON")
def turn_off(self):
print("Light is OFF")
# ConcreteCommand
class TurnOnCommand(Command):
def __init__(self, light):
self._light = light
def execute(self):
self._light.turn_on()
class TurnOffCommand(Command):
def __init__(self, light):
self._light = light
def execute(self):
self._light.turn_off()
# Invoker
class RemoteControl:
def __init__(self):
self._command = None
def set_command(self, command):
self._command = command
def press_button(self):
if self._command:
self._command.execute()
# Client
if __name__ == "__main__":
light = Light()
turn_on = TurnOnCommand(light)
turn_off = TurnOffCommand(light)
remote = RemoteControl()
remote.set_command(turn_on)
remote.press_button() # 輸出: Light is ON
remote.set_command(turn_off)
remote.press_button() # 輸出: Light is OFF
如上例所示,完全按照命令模式的標準結構實現。
優點: - 結構清晰 - 易于擴展新命令 - 支持撤銷/重做
Python中函數是一等對象,可以直接作為命令使用:
def light_on():
print("Light is ON")
def light_off():
print("Light is OFF")
class FunctionCommand:
def __init__(self, func):
self.func = func
def execute(self):
self.func()
# 使用
cmd_on = FunctionCommand(light_on)
cmd_off = FunctionCommand(light_off)
controller = RemoteControl()
controller.set_command(cmd_on)
controller.press_button()
def make_light_command(light, action):
def execute():
if action == 'on':
light.turn_on()
elif action == 'off':
light.turn_off()
return execute
light = Light()
cmd_on = make_light_command(light, 'on')
cmd_off = make_light_command(light, 'off')
controller.set_command(cmd_on)
controller.press_button()
擴展Command接口添加undo方法:
class Command(ABC):
@abstractmethod
def execute(self):
pass
@abstractmethod
def undo(self):
pass
class TurnOnCommand(Command):
def __init__(self, light):
self._light = light
def execute(self):
self._light.turn_on()
def undo(self):
self._light.turn_off()
# Invoker需要維護歷史記錄
class AdvancedRemoteControl:
def __init__(self):
self._commands = []
def execute_command(self, command):
command.execute()
self._commands.append(command)
def undo_last(self):
if self._commands:
last_command = self._commands.pop()
last_command.undo()
class MacroCommand(Command):
def __init__(self, commands):
self._commands = commands
def execute(self):
for cmd in self._commands:
cmd.execute()
def undo(self):
for cmd in reversed(self._commands):
cmd.undo()
# 使用
macro = MacroCommand([turn_on, turn_off])
controller.execute_command(macro)
import threading
from queue import Queue
class ThreadPool:
def __init__(self, num_threads):
self.task_queue = Queue()
self.threads = [
threading.Thread(target=self._worker)
for _ in range(num_threads)
]
for t in self.threads:
t.start()
def _worker(self):
while True:
command = self.task_queue.get()
command.execute()
self.task_queue.task_done()
def add_task(self, command):
self.task_queue.put(command)
# 使用
pool = ThreadPool(4)
pool.add_task(turn_on)
pool.add_task(turn_off)
class MenuItem:
def __init__(self, label, command):
self.label = label
self.command = command
def click(self):
self.command.execute()
# 創建菜單
save_command = SaveFileCommand(document)
menu_item = MenuItem("Save", save_command)
class InputHandler:
def __init__(self):
self._key_bindings = {}
def bind_key(self, key, command):
self._key_bindings[key] = command
def handle_input(self):
pressed_key = get_pressed_key()
if pressed_key in self._key_bindings:
self._key_bindings[pressed_key].execute()
# 配置按鍵
handler = InputHandler()
handler.bind_key('SPACE', JumpCommand(player))
handler.bind_key('A', MoveLeftCommand(player))
class Transaction:
def __init__(self):
self._commands = []
def add_command(self, command):
self._commands.append(command)
def commit(self):
for cmd in self._commands:
cmd.execute()
def rollback(self):
for cmd in reversed(self._commands):
cmd.undo()
# 使用
tx = Transaction()
tx.add_command(UpdateCommand(db, "SET balance = balance - 100 WHERE id = 1"))
tx.add_command(UpdateCommand(db, "SET balance = balance + 100 WHERE id = 2"))
tx.commit() # 執行事務
命令模式在Python中可以通過多種方式實現: - 經典類實現適合復雜場景 - 函數式實現更Pythonic - 閉包方式簡潔但可讀性稍差
實際應用中,命令模式特別適合: - 需要實現撤銷/重做功能 - 需要將操作排隊或記錄 - 需要支持事務的系統 - GUI事件處理
通過合理使用命令模式,可以使代碼更加靈活、可維護,并為系統提供強大的擴展能力。 “`
這篇文章總計約1900字,涵蓋了命令模式的核心概念、Python實現方式、高級應用場景以及優缺點分析,采用Markdown格式并包含代碼示例。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。