GOF设计模式分三大类:
如果还没有阅读第一部分,可以点击这里进行回顾:《设计模式Python版 命令模式(上)》。现在,继续第二部分。
命令队列
"""命令队列"""
class CmdQueue:
def __init__(self):
self.cmds: list[Cmd] = [] # 存储命令队列
def add_cmd(self, cmd: Cmd):
if cmd not in self.cmds:
self.cmds.append(cmd)
def remove_cmd(self, cmd: Cmd):
if cmd in self.cmds:
self.cmds.remove(cmd)
def execute(self):
# 调用每一个命令对象的execute()方法
for i in self.cmds:
i.execute()
"""请求发送者"""
class Invoker:
def __init__(self, cmd_queue: CmdQueue):
self.cmd_queue = cmd_queue # CmdQueue的引用
def call(self):
self.cmd_queue.execute()
在命令模式中,可以通过调用一个命令对象的execute()方法来实现对请求的处理。如果需要撤销(Undo)请求,可通过在命令类中增加一个逆向操作来实现。
"""请求发送者"""
class CalculatorForm:
def __init__(self):
self.cmd: AbstractCmd = None
def compute(self, value: int):
i = self.cmd.execute(value)
print(f"执行运算,运算结果为:{i}")
def undo(self):
i = self.cmd.undo()
print(f"执行撤销,运算结果为:{i}")
"""请求接收者"""
class Adder:
def __init__(self):
self.num = 0 # 初始值为0
def add(self, value: int) -> int:
# 每次将传入的值与num作加法运算,再将结果返回
self.num += value
return self.num
"""抽象命令类"""
class AbstractCmd:
# 执行方法
def execute(self, value: int) -> int:
raise NotImplementedError
# 撤销方法
def undo(self) -> int:
raise NotImplementedError
"""具体命令类"""
class AddCmd(AbstractCmd):
def __init__(self):
self.adder = Adder()
def execute(self, value):
# 调用加法类的加法操作
self.value = value
return self.adder.add(value)
def undo(self):
# 通过加一个相反数来实现加法的逆向操作
return self.adder.add(-self.value)
form = CalculatorForm()
cmd: AbstractCmd = AddCmd()
form.cmd = cmd
form.compute(10)
form.compute(5)
form.compute(10)
form.undo()
执行运算,运算结果为:10
执行运算,运算结果为:15
执行运算,运算结果为:25
执行撤销,运算结果为:15
请求日志就是将请求的历史记录保存下来,通常以日志文件(Log File)的形式永久存储在计算机中。
示例:将对网站配置文件的操作请求记录在日志文件中,如果网站重新部署,只需要执行保存在日志文件中的命令对象即可修改配置文件。
from pathlib import Path
import pickle
"""请求发送者"""
class ConfigSettingWindow:
# 配置文件设置窗口
def __init__(self):
self.cmds: list[Cmd] = [] # 存储每一次操作时的命令对象
self.cmd: Cmd = None
def call(self, args):
# 执行配置文件修改命令,同时将命令对象添加到命令集合中
self.cmd.execute(args)
self.cmds.append(self.cmd)
def save(self):
# 将命令集合写入日志文件
FileUtil.write_cmds(self.cmds)
def recover(self):
# 从日志文件中提取命令集合,并遍历调用每一个命令对象的execute()方法来实现配置文件的重新设置
cmds = FileUtil.read_cmds()
for i in cmds:
i.execute(i.args)
"""请求接收者"""
class ConfigOperator:
# 配置文件操作
def insert(self, args: str):
print(f"增加新节点:{args}")
def modify(self, args: str):
print(f"修改节点:{args}")
def delete(self, args: str):
print(f"删除节点:{args}")
"""抽象命令类"""
class Cmd:
def __init__(self, name: str):
self.name = name
self.config_operator: ConfigOperator = None # 请求接收者对象的引用
self.args = None
def execute(self, args):
raise NotImplementedError
"""具体命令类"""
class InsertCmd(Cmd):
# 增加
def __init__(self, name):
super().__init__(name)
def execute(self, args):
self.args = args
self.config_operator.insert(args)
class ModifyCmd(Cmd):
# 修改
def __init__(self, name):
super().__init__(name)
def execute(self, args):
self.args = args
self.config_operator.modify(args)
class DeleteCmd(Cmd):
# 删除
def __init__(self, name):
super().__init__(name)
def execute(self, args):
self.args = args
self.config_operator.delete(args)
"""工具类:文件操作"""
class FileUtil:
@staticmethod
def write_cmds(cmds: list[Cmd]):
# 将命令集合写入日志文件
try:
file = Path("command_config.log")
contents = pickle.dumps(cmds)
file.write_bytes(contents)
except Exception as e:
print("命令保存失败!")
print(e)
@staticmethod
def read_cmds() -> list[Cmd]:
# 从日志文件中提取命令集合
try:
file = Path("command_config.log")
contents = file.read_bytes()
cmds = pickle.loads(contents)
return cmds
except Exception as e:
print("命令读取失败!")
print(e)
if __name__ == "__main__":
csw = ConfigSettingWindow() # 定义请求发送者
co = ConfigOperator() # 定义请求接收者
# 4次对配置文件进行更必
cmd = InsertCmd("增加")
cmd.config_operator = co
csw.cmd = cmd
csw.call("网站首页")
cmd = InsertCmd("增加")
cmd.config_operator = co
csw.cmd = cmd
csw.call("端口号")
cmd = ModifyCmd("修改")
cmd.config_operator = co
csw.cmd = cmd
csw.call("网站首页")
cmd = ModifyCmd("修改")
cmd.config_operator = co
csw.cmd = cmd
csw.call("端口号")
print("#" * 20)
print("保存配置")
csw.save()
print("#" * 20)
print("恢复配置")
csw.recover()
增加新节点:网站首页
增加新节点:端口号
修改节点:网站首页
修改节点:端口号
####################
保存配置
####################
恢复配置
增加新节点:网站首页
增加新节点:端口号
修改节点:网站首页
修改节点:端口号
宏命令
您正在阅读的是《设计模式Python版》专栏!关注不迷路~