前言
彼岸花开一千年,花开花落不相见。 若问花开叶落故,彼岸缘起缘又灭——《我欲封天》
\;\\\;\\\;
目录
- 前言
- 简单的设计模式
- 复杂的设计模式
- 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):@abstractmethoddef set_next(self, handler: Handler) -> Handler:pass@abstractmethoddef handle(self, request) -> Optional[str]:pass#第2层处理者
class SomeHandler(Handler):_next_handler: Handler = Nonedef set_next(self, handler: Handler) -> Handler:self._next_handler = handlerreturn handler@abstractmethoddef 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 Anyclass 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或-1def __next__(self) -> Any:"""获取下一个元素,如果没有则抛出 StopIteration"""try:value = self._collection[self._position] # 获取当前元素self._position += -1 if self._reverse else 1 # 移动位置,1往后易懂,-1往前易懂except IndexError:raise StopIteration() # 遍历结束时抛出 StopIterationreturn valueclass 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 = Nonedef __init__(self, state: str) -> None:self._state = stateprint(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}")#获取随机字母组合的字符串,通常做密码都会用到这种函数@staticmethoddef _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):@abstractmethoddef get_name(self) -> str:pass@abstractmethoddef get_date(self) -> str:pass# 第2层备忘录
class ConcreteMemento(Memento):def __init__(self, state: str) -> None:self._state = stateself._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):returnmemento = 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):@propertydef Manager(self) -> Manager:return self._Manager@Manager.setterdef Manager(self, Manager: Manager) -> None:self._Manager = Manager@abstractmethoddef handle1(self) -> None:pass@abstractmethoddef 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 = Nonedef __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 = stateself._state.Manager = selfdef 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")#抽象方法:下面两个函数必须由子类实现@abstractmethoddef required_operations1(self) -> None:pass@abstractmethoddef required_operations2(self) -> None:pass#普通函数:下面两个函数可以由父类实现,也可以被子类覆盖def hook1(self) -> None:passdef 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):@abstractmethoddef 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):@abstractmethoddef visit_warrior(self, character: Warrior) -> None:pass@abstractmethoddef 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):@abstractmethoddef attach(self, People: People) -> None:pass@abstractmethoddef detach(self, People: People) -> None:pass@abstractmethoddef 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):@abstractmethoddef 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()#加入玩家1People_a = Player()Interaction.attach(People_a)#加入玩家2People_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):@abstractmethoddef exec(self) -> None:pass# 第2层命令
class SimpleCommand(Command):def __init__(self, payload: str) -> None:self._payload = payloaddef 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 = NPCself._a = aself._b = bdef 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 = Nonedef set_on_start(self, command: Command):self._on_start = commanddef set_on_finish(self, command: Command):self._on_finish = commanddef 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@propertydef strategy(self) -> Strategy:return self._strategy@strategy.setterdef strategy(self, strategy: Strategy) -> None:self._strategy = strategydef run(self) -> None:print("Context:run")result = self._strategy.calc(["a", "b", "c", "d", "e"])print(",".join(result))#第一层策略
class Strategy(ABC):@abstractmethoddef 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 = component1self._component1.mediator = self #关键self._component2 = component2self._component2.mediator = self #关键def notify(self, sender: object, event: str) -> None:if event == "A":self._component2.do_c() #前面执行了A,这里就会执行Celif event == "D":self._component1.do_b() #前面执行了D,这里就会执行B,Cself._component2.do_c()#第一层组件
class Component:def __init__(self, mediator: Mediator = None) -> None:self._mediator = mediator@propertydef mediator(self) -> Mediator:return self._mediator@mediator.setterdef 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):@abstractmethoddef interpret(self, context: Dict[str, int]) -> int:pass# 具体表达式:变量表达式
class VariableExpression(Expression):def __init__(self, variable: str) -> None:self.variable = variabledef interpret(self, context: Dict[str, int]) -> int:return context[self.variable]# 具体表达式:常量表达式
class LiteralExpression(Expression):def __init__(self, value: int) -> None:self.value = valuedef interpret(self, context: Dict[str, int]) -> int:return self.value# 具体表达式:加法表达式
class AddExpression(Expression):def __init__(self, left: Expression, right: Expression) -> None:self.left = leftself.right = rightdef 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 = leftself.right = rightdef 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()
\;\\\;\\\;