前言
彼岸花开一千年,花开花落不相见。 若问花开叶落故,彼岸缘起缘又灭——《我欲封天》
\;\\\;\\\;
目录
- 前言
- 简单的设计模式
- 复杂的设计模式
- 13责任链
- 14迭代器
- 15备忘录
- 16状态机
- 17模板方法
- 18访问者
- 19观察者
- 20命令Shell
- 21策略
- 22调解
- 23解释器
简单的设计模式
见上篇
\;\\\;\\\;
复杂的设计模式
13责任链
一个类跟着一个类,虽然用链表也能处理(甚至是没什么用的静态链表(数组)也行)。
但是责任链添加了处理者的类,这样实际的第三层类就不用处理set_next和handle了。
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import Any, Optional
#第一层处理者
class Handler(ABC):
@abstractmethod
def set_next(self, handler: Handler) -> Handler:
pass
@abstractmethod
def handle(self, request) -> Optional[str]:
pass
#第2层处理者
class SomeHandler(Handler):
_next_handler: Handler = None
def set_next(self, handler: Handler) -> Handler:
self._next_handler = handler
return handler
@abstractmethod
def handle(self, request: Any) -> str:
if self._next_handler:
return self._next_handler.handle(request)
return None
#第3层处理者
class MonkeyHandler(SomeHandler):
def handle(self, request: Any) -> str:
if request == "Banana":
return f"Monkey: I'll eat the <{request}>"
else:
return super().handle(request)
#第3层处理者
class SquirrelHandler(SomeHandler):
def handle(self, request: Any) -> str:
if request == "Nut":
return f"Squirrel: I'll eat the <{request}>"
else:
return super().handle(request)
#第3层处理者
class DogHandler(SomeHandler):
def handle(self, request: Any) -> str:
if request == "MeatBall":
return f"Dog: I'll eat the <{request}>"
else:
return super().handle(request)
#客户代码
def client_code(handler: Handler) -> None:
for food in ["Nut", "Banana", "Cup of coffee"]:
print(f"Client: Who wants a <{food}>?")
result = handler.handle(food)
if result:
print(f" {result}", end="\n")
else:
print(f" <{food}> was left untouched.", end="\n")
def Main():
monkey = MonkeyHandler()
squirrel = SquirrelHandler()
dog = DogHandler()
monkey.set_next(squirrel).set_next(dog)
print("Chain: Monkey > Squirrel > Dog")
client_code(monkey)
print("\n")
print("Subchain: Squirrel > Dog")
client_code(squirrel)
if __name__ == "__main__":
Main()
\;\\\;\\\;
14迭代器
python封装迭代器的固定写法。
from __future__ import annotations
from collections.abc import Iterable, Iterator
from typing import Any
class MyIterator(Iterator):
_position: int = None # 当前迭代位置
_reverse: bool = False # 是否反向迭代
def __init__(self, collection: WordsCollection, reverse: bool = False) -> None:
self._collection = collection # 关联的可迭代对象
self._reverse = reverse # 是否反向遍历
self._position = -1 if reverse else 0 # 初始化位置0或-1
def __next__(self) -> Any:
"""获取下一个元素,如果没有则抛出 StopIteration"""
try:
value = self._collection[self._position] # 获取当前元素
self._position += -1 if self._reverse else 1 # 移动位置,1往后易懂,-1往前易懂
except IndexError:
raise StopIteration() # 遍历结束时抛出 StopIteration
return value
class WordsCollection(Iterable):
def __init__(self, collection: list[Any] | None = None) -> None:
self._collection = collection or []
def __getitem__(self, index: int) -> Any:
return self._collection[index]
def __iter__(self) -> MyIterator:
return MyIterator(self)
def get_reverse_iterator(self) -> MyIterator:
return MyIterator(self, True)
def add_item(self, item: Any) -> None:
self._collection.append(item)
def Main():
collection = WordsCollection()
collection.add_item("First")
collection.add_item("Second")
collection.add_item("Third")
#遍历
print("Straight traversal:")
print("\n".join(collection))
print("")
#反方向遍历
print("Reverse traversal:")
print("\n".join(collection.get_reverse_iterator()), end="")
if __name__ == "__main__":
Main()
\;\\\;\\\;
15备忘录
用链表和数组什么的实现也可以,这就是内存的log。如果数据量大,这个数据就要写入文件,撤销的时候从文件中恢复。
_generate_random_string() 这个让我想起了昨天看的B站视频@epcdiy,说是windows下的勒索软件加密了文件,然后up主研究发现原理就是先随机获取16个字母,然后再拿RSA加密什么的。
from __future__ import annotations
from abc import ABC, abstractmethod
from datetime import datetime
from random import sample
from string import ascii_letters
#状态持有者
class StateHolder:
_state = None
def __init__(self, state: str) -> None:
self._state = state
print(f"StateHolder: My initial state is: {self._state}")
def run(self) -> None:
print("StateHolder:run -> ",end="")
self._state = self._generate_random_string(30)
print(f"my state has changed to: {self._state}")
#获取随机字母组合的字符串,通常做密码都会用到这种函数
@staticmethod
def _generate_random_string(length: int = 10) -> str:
return "".join(sample(ascii_letters, length))
#保存
def save(self) -> Memento:
return ConcreteMemento(self._state)
#恢复
def restore(self, memento: Memento) -> None:
self._state = memento.get_state()
print(f"StateHolder: My state has changed to: {self._state}")
#第一层备忘录
class Memento(ABC):
@abstractmethod
def get_name(self) -> str:
pass
@abstractmethod
def get_date(self) -> str:
pass
# 第2层备忘录
class ConcreteMemento(Memento):
def __init__(self, state: str) -> None:
self._state = state
self._date = str(datetime.now())[:19]
#获取状态
def get_state(self) -> str:
return self._state
#获取
def get_name(self) -> str:
return f"{self._date} / ({self._state[0:9]}...)"
#获取日期
def get_date(self) -> str:
return self._date
#管理者
#一个链表保存N个状态,每个状态中嵌套当时的时间
class Manager:
def __init__(self, s: StateHolder) -> None:
self._mementos = []
self._StateHolder = s
#备份
def backup(self) -> None:
print("\nManager: Saving StateHolder's state...")
self._mementos.append(self._StateHolder.save())
#撤销
def undo(self) -> None:
if not len(self._mementos):
return
memento = self._mementos.pop()
print(f"Manager: Restoring state to: {memento.get_name()}")
try:
self._StateHolder.restore(memento)
except Exception:
self.undo()
#打印历史
def show_history(self) -> None:
print("Manager: Here's the list of mementos:")
for memento in self._mementos:
print(memento.get_name())
def Main():
s = StateHolder("Super-duper-super-puper-super.") #最初始的状态
m = Manager(s)
m.backup() #备份
s.run()
m.backup()
s.run()
m.backup()
s.run()
print("---------------------------------------------------------------------\n")
m.show_history()
print("\nClient: Now, let's rollback!\n")
m.undo() #撤销
print("\nClient: Once more!\n")
m.undo() #撤销
if __name__ == "__main__":
Main()
\;\\\;\\\;
16状态机
这不是一种好方法,前后两个状态,加上转换,这些固定在了代码中。如果状态和转换特别多,甚至有各自输入输出就完了。
我之前的博客有写过,状态要单独拎出来,其中不要写转换到哪。
写一个类为规则,一条规则传入两个状态就好。具体转换到哪,先遍历一条条规则,每个规则固定从前面状态转到后面状态,还要结合转换条件——Mealy状态机或者Moore状态机。
from __future__ import annotations
from abc import ABC, abstractmethod
#第一层状态
class State(ABC):
@property
def Manager(self) -> Manager:
return self._Manager
@Manager.setter
def Manager(self, Manager: Manager) -> None:
self._Manager = Manager
@abstractmethod
def handle1(self) -> None:
pass
@abstractmethod
def handle2(self) -> None:
pass
#第2层状态
class ConcreteStateA(State):
def handle1(self) -> None:
print("ConcreteStateA:handle1")
print("\twants to change the state of the Manager.")
self.Manager.transition_to(ConcreteStateB())
def handle2(self) -> None:
print("ConcreteStateA:handle2")
#第2层状态
class ConcreteStateB(State):
def handle1(self) -> None:
print("ConcreteStateB:handle1")
def handle2(self) -> None:
print("ConcreteStateB:handle2")
print("\twants to change the state of the Manager.")
self.Manager.transition_to(ConcreteStateA())
#管理者
class Manager:
_state = None
def __init__(self, state: State) -> None:
self.transition_to(state)
def transition_to(self, state: State):
print(f"Manager: Transition to {type(state).__name__}")
self._state = state
self._state.Manager = self
def request1(self):
self._state.handle1()
def request2(self):
self._state.handle2()
def Main():
m = Manager(ConcreteStateA())
m.request1()
m.request2()
if __name__ == "__main__":
Main()
\;\\\;\\\;
17模板方法
不同具体子类的执行框架,已经在父类中固定了、
from abc import ABC, abstractmethod
#第一层人
class People(ABC):
def template_method(self) -> None:
self.base_operation1()
self.required_operations1()
self.base_operation2()
self.hook1()
self.required_operations2()
self.base_operation3()
self.hook2()
def base_operation1(self) -> None:
print("People:base_operation1")
def base_operation2(self) -> None:
print("People:base_operation2")
def base_operation3(self) -> None:
print("People:base_operation3")
#抽象方法:下面两个函数必须由子类实现
@abstractmethod
def required_operations1(self) -> None:
pass
@abstractmethod
def required_operations2(self) -> None:
pass
#普通函数:下面两个函数可以由父类实现,也可以被子类覆盖
def hook1(self) -> None:
pass
def hook2(self) -> None:
pass
#第二层人
class Teacher(People):
def required_operations1(self) -> None:
print("Teacher:required_operations1")
def required_operations2(self) -> None:
print("Teacher:required_operations2")
#第二层人
class Student(People):
def required_operations1(self) -> None:
print("Student:required_operations1")
def required_operations2(self) -> None:
print("Student:required_operations2")
def hook1(self) -> None:
print("Student:hook1")
#客户代码
def client_code(abstract_class: People) -> None:
abstract_class.template_method()
def Main():
client_code(Teacher())
print("")
client_code(Student())
if __name__ == "__main__":
Main()
\;\\\;\\\;
18访问者
两棵树,一颗被访问者树,一颗访问者树。被访问者会调用访问者,即物体调用行为。
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import List
# 抽象角色
class Character(ABC):
@abstractmethod
def accept(self, action: Action) -> None:
pass
# 具体角色:战士
class Warrior(Character):
def accept(self, action: Action) -> None:
action.visit_warrior(self)
def attack(self) -> str:
return "Warrior: Strong attack"
def defend(self) -> str:
return "Warrior: Solid defense"
# 具体角色:法师
class Mage(Character):
def accept(self, action: Action) -> None:
action.visit_mage(self)
def cast_spell(self) -> str:
return "Mage: Powerful spell"
def heal(self) -> str:
return "Mage: Healing magic"
# 抽象行为
class Action(ABC):
@abstractmethod
def visit_warrior(self, character: Warrior) -> None:
pass
@abstractmethod
def visit_mage(self, character: Mage) -> None:
pass
# 具体行为:攻击行为
class AttackAction(Action):
def visit_warrior(self, character: Warrior) -> None:
print(f"{character.attack()} with AttackAction")
def visit_mage(self, character: Mage) -> None:
print(f"{character.cast_spell()} with AttackAction")
# 具体行为:防御行为
class DefendAction(Action):
def visit_warrior(self, character: Warrior) -> None:
print(f"{character.defend()} with DefendAction")
def visit_mage(self, character: Mage) -> None:
print(f"{character.heal()} with DefendAction")
# 客户端代码
def client_code(characters: List[Character], action: Action) -> None:
for character in characters:
character.accept(action)
# 主函数
def main():
characters = [Warrior(), Mage()]
print("The client code works with all characters via the base Action interface:")
attack_action = AttackAction()
client_code(characters, attack_action)
print("\nIt allows the same client code to work with different types of actions:")
defend_action = DefendAction()
client_code(characters, defend_action)
if __name__ == "__main__":
main()
\;\\\;\\\;
19观察者
一对多,多个观察者观察一个对象。
from __future__ import annotations
from abc import ABC, abstractmethod
from random import randrange
from typing import List
#第一层交互
class Interaction(ABC):
@abstractmethod
def attach(self, People: People) -> None:
pass
@abstractmethod
def detach(self, People: People) -> None:
pass
@abstractmethod
def notify(self) -> None:
pass
#第2层交互
class ConcreteInteraction(Interaction):
_state: int = None
_Peoples: List[People] = []
def attach(self, p: People) -> None:
print("ConcreteInteraction:attach")
self._Peoples.append(p)
def detach(self, p: People) -> None:
self._Peoples.remove(p)
def notify(self) -> None:
print("ConcreteInteraction:notify")
for People in self._Peoples:
People.update(self)
def battle(self) -> None:
print("\nConcreteInteraction:battle -> ",end="")
self._state = randrange(0, 10)
print(f"My state has just changed to: {self._state}")
self.notify()
#第一层观察者
class People(ABC):
@abstractmethod
def update(self, Interaction: Interaction) -> None:
pass
#第2层观察者
class Player(People):
def update(self, Interaction: Interaction) -> None:
if Interaction._state < 3:
print("Player:update")
# 第2层观察者
class Monster(People):
def update(self, Interaction: Interaction) -> None:
if Interaction._state == 0 or Interaction._state >= 2:
print("Monster: Reacted to the event")
def Main():
Interaction = ConcreteInteraction()
#加入玩家1
People_a = Player()
Interaction.attach(People_a)
#加入玩家2
People_b = Monster()
Interaction.attach(People_b)
#开始战斗
Interaction.battle()
Interaction.battle()
Interaction.detach(People_a) #移除玩家1
#继续战斗
Interaction.battle()
if __name__ == "__main__":
Main()
\;\\\;\\\;
20命令Shell
很多设计模式都是这种三方模式,一边的抽象树是被操作者,一边的抽象树是操作者,还有第三方类是管理者。
from __future__ import annotations
from abc import ABC, abstractmethod
#第一层命令
class Command(ABC):
@abstractmethod
def exec(self) -> None:
pass
# 第2层命令
class SimpleCommand(Command):
def __init__(self, payload: str) -> None:
self._payload = payload
def exec(self) -> None:
print(f"SimpleCommand:exec -> {self._payload}")
# 第2层命令
class ComplexCommand(Command):
def __init__(self, NPC: NPC, a: str, b: str) -> None:
self._NPC = NPC
self._a = a
self._b = b
def exec(self) -> None:
print("ComplexCommand:exec")
self._NPC.do_something(self._a)
self._NPC.do_something_else(self._b)
#被操作者
class NPC:
def do_something(self, a: str) -> None:
print(f"\nNPC: Working on : {a}", end="")
def do_something_else(self, b: str) -> None:
print(f"\nNPC: Also working on : {b}", end="")
#管理者
class Manager:
_on_start = None
_on_finish = None
def set_on_start(self, command: Command):
self._on_start = command
def set_on_finish(self, command: Command):
self._on_finish = command
def do_something_important(self) -> None:
print("Manager:1")
if isinstance(self._on_start, Command):
self._on_start.exec()
print("Manager:2")
print("Manager:3")
if isinstance(self._on_finish, Command):
self._on_finish.exec()
def Main():
a = Manager()
a.set_on_start(SimpleCommand("Say Hi!"))
r = NPC()
a.set_on_finish(ComplexCommand(r, "Send email", "Save report"))
a.do_something_important()
if __name__ == "__main__":
Main()
\;\\\;\\\;
21策略
相当于C++ STL使用排序或者查找函数式,要传入的形参函数指针,根据用户实现的函数,来具体按什么属性查找,或者按什么顺序查找等操作。
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import List
#持有一个策略实例。这个类作用是提供一个接口,让客户端可以调用策略算法
class Context():
def __init__(self, strategy: Strategy) -> None:
self._strategy = strategy
@property
def strategy(self) -> Strategy:
return self._strategy
@strategy.setter
def strategy(self, strategy: Strategy) -> None:
self._strategy = strategy
def run(self) -> None:
print("Context:run")
result = self._strategy.calc(["a", "b", "c", "d", "e"])
print(",".join(result))
#第一层策略
class Strategy(ABC):
@abstractmethod
def calc(self, data: List):
pass
#第2层策略
class ConcreteStrategyA(Strategy):
def calc(self, data: List) -> List:
return sorted(data)
#第2层策略
class ConcreteStrategyB(Strategy):
def calc(self, data: List) -> List:
return reversed(sorted(data))
def Main():
context = Context(ConcreteStrategyA())
print("Client: Strategy is set to normal sorting.")
context.run()
print()
print("Client: Strategy is set to reverse sorting.")
context.strategy = ConcreteStrategyB()
context.run()
if __name__ == "__main__":
Main()
\;\\\;\\\;
22调解
组件和调解器相互调用,这样能保证解耦,即组件之间不会相互调用。
from __future__ import annotations
from abc import ABC
#第一层调解器
class Mediator(ABC):
def notify(self, sender: object, event: str) -> None:
pass
#第2层调解器
class ConcreteMediator(Mediator):
def __init__(self, component1: Component1, component2: Component2) -> None:
self._component1 = component1
self._component1.mediator = self #关键
self._component2 = component2
self._component2.mediator = self #关键
def notify(self, sender: object, event: str) -> None:
if event == "A":
self._component2.do_c() #前面执行了A,这里就会执行C
elif event == "D":
self._component1.do_b() #前面执行了D,这里就会执行B,C
self._component2.do_c()
#第一层组件
class Component:
def __init__(self, mediator: Mediator = None) -> None:
self._mediator = mediator
@property
def mediator(self) -> Mediator:
return self._mediator
@mediator.setter
def mediator(self, mediator: Mediator) -> None:
self._mediator = mediator
#第2层组件
class Component1(Component):
def do_a(self) -> None:
print("Component1:do_a")
self.mediator.notify(self, "A")
def do_b(self) -> None:
print("Component1:do_b")
self.mediator.notify(self, "B")
#第2层组件
class Component2(Component):
def do_c(self) -> None:
print("Component1:do_c")
self.mediator.notify(self, "C")
def do_d(self) -> None:
print("Component1:do_d")
self.mediator.notify(self, "D")
def Main():
c1 = Component1()
c2 = Component2()
mediator = ConcreteMediator(c1, c2)
print("Client triggers operation A.")
c1.do_a()
print()
print("Client triggers operation D.")
c2.do_d()
if __name__ == "__main__":
Main()
\;\\\;\\\;
23解释器
做编译器的时候用了好多次,原因是树太多了。表达式树,操作符树,类型值树,符号表树,,,,
from abc import ABC, abstractmethod
from typing import Dict
# 抽象表达式
class Expression(ABC):
@abstractmethod
def interpret(self, context: Dict[str, int]) -> int:
pass
# 具体表达式:变量表达式
class VariableExpression(Expression):
def __init__(self, variable: str) -> None:
self.variable = variable
def interpret(self, context: Dict[str, int]) -> int:
return context[self.variable]
# 具体表达式:常量表达式
class LiteralExpression(Expression):
def __init__(self, value: int) -> None:
self.value = value
def interpret(self, context: Dict[str, int]) -> int:
return self.value
# 具体表达式:加法表达式
class AddExpression(Expression):
def __init__(self, left: Expression, right: Expression) -> None:
self.left = left
self.right = right
def interpret(self, context: Dict[str, int]) -> int:
return self.left.interpret(context) + self.right.interpret(context)
# 具体表达式:减法表达式
class SubtractExpression(Expression):
def __init__(self, left: Expression, right: Expression) -> None:
self.left = left
self.right = right
def interpret(self, context: Dict[str, int]) -> int:
return self.left.interpret(context) - self.right.interpret(context)
def Main():
# 定义变量和常量
x = VariableExpression("x")
y = VariableExpression("y")
five = LiteralExpression(5)
# 定义表达式
expression = AddExpression(SubtractExpression(x, y), five)
# 上下文环境
context = {"x": 10, "y": 3}
# 解释并执行表达式
result = expression.interpret(context)
print(f"Result of the expression: {result}")
if __name__ == "__main__":
Main()
\;\\\;\\\;