23种经典设计模式
参考
-
人人都懂设计模式:从生活中领悟设计模式(Python实现)
-
设计模式:可复用面向对象软件的基础
该书学术性太强
1. 观察者模式
1.1 基础知识
- 又称发布订阅模式(publish / subscribe ),监听模式
- 是一种一对多的关系
- 一个被观察者(Observable或Subject)
- 多个观察者(Observer)
- 被观察者在其状态或者数据发生变化时,通知全部观察者
- Observable 调用 Observer的update方法
- 被观察者至少提供三种方法
- 添加观察者(attach / register)
- 删除观察者(detach / unregister)
- 更新状态(notify)
1.2 代码框架
1.2.1 基础版本
class Subject:
def __init__(self) -> None:
self.observer_list = []
def register(self, observer):
self.observer_list.append(observer)
def unregister(self, observer):
self.observer_list.remove(observer)
def notify(self, message):
for observer in self.observer_list:
observer.update(message)
def func(self):
pass
self.notify('Hello')
class Observer:
def __init__(self) -> None:
pass
def update(self, message):
print(f"Observer received: {message}")
if __name__ == "__main__":
subject = Subject()
observer = Observer()
subject.register(observer)
subject.func()
1.2.2 推模型
被观察者向全部观察者推送信息(也可以直接把自身推送过去)
- 比如反诈中心的公益短信
class Subject:
def __init__(self) -> None:
self.observer_list = []
def register(self, observer):
self.observer_list.append(observer)
def unregister(self, observer):
self.observer_list.remove(observer)
def notify(self):
for observer in self.observer_list:
observer.update(self)
def func(self):
self.message = "Hello"
self.notify()
class Observer:
def __init__(self) -> None:
pass
def update(self, obj):
print(f"Observer received: {obj.message}")
if __name__ == "__main__":
subject = Subject()
observer = Observer()
subject.register(observer)
subject.func()
1.2.3 拉模型
只向全部观察者,推送通知。由观察者自行决定,是否拉取全部信息
- 相比于推模型,拉模型更节省流量
- 比如手机系统更新,厂家会给每个用户发送更新通知,由用户自行决定是否更新系统
class Subject:
def __init__(self):
self._observers = []
self._state = None
def attach(self, observer):
if observer not in self._observers:
self._observers.append(observer)
def detach(self, observer):
self._observers.remove(observer)
def notify(self, message):
for observer in self._observers:
observer.update(message)
def get_state(self):
return self._state
def set_state(self, state):
self._state = state
self.notify("message")
class Observer:
def __init__(self, subject):
self._subject = subject
self._subject.attach(self)
def update(self, message):
# 可根据message做对应处理
state = self._subject.get_state()
print(f"Observer {id(self)} received update: {state}")
# 示例用法
if __name__ == "__main__":
subject = Subject()
observer1 = Observer(subject)
subject.set_state("State 1")
2. 状态模式
2.1 基础知识
-
状态模式:当一个对象的内部状态改变后,对象的行为也发生变化
-
适用条件
- 对象的行为由状态决定
- 不同的状态之间的行为差异很大
如果行为差异比较小或易管理,直接用if-elif-else分支即可
-
状态模式构成的要点
- 每个状态及其对应行为封装成类(全局单例),且继承自同一父类
- 使用状态的类,直接访问状态父类的方法,进而实现多态
2.2 代码框架
(Deepseek生成)
from abc import ABC, abstractmethod
# 状态接口
class State(ABC):
@abstractmethod
def handle(self, context):
pass
# 具体状态类
class ConcreteStateA(State):
def handle(self, context):
print("ConcreteStateA is handling the request.")
# 状态转换逻辑
context.set_state(ConcreteStateB())
class ConcreteStateB(State):
def handle(self, context):
print("ConcreteStateB is handling the request.")
# 状态转换逻辑
context.set_state(ConcreteStateA())
# 上下文类
class Context:
def __init__(self):
self._state = ConcreteStateA() # 初始状态
def set_state(self, state):
self._state = state
print(f"State changed to {state.__class__.__name__}")
def request(self):
self._state.handle(self)
# 示例用法
if __name__ == "__main__":
context = Context()
context.request() # ConcreteStateA is handling the request.
context.request() # ConcreteStateB is handling the request.
context.request() # ConcreteStateA is handling the request.
为简化逻辑,建议状态转换由上下文类完成。每个状态类,仅负责行为函数多态。
3. 中介模式
3.1 基础概念
-
Mediator Pattern:中介者使个对象不需要显示的相互引用,从而使其耦合松散
- 变成星型结构,中介者做核心
-
在应用上,可以有效避免各模块间的相互引用,进而避免循环引用
3.2 代码框架
并不存在一个通用框架,只要该代码框架满足:
- 星型结构:各对象仅依赖中介者,而不是其他对象
- 中介交互:各对象通过中介者进行交互,而不是直接交互
简单案例:聊天室
from abc import ABC, abstractmethod
# 抽象中介者
class Mediator(ABC):
@abstractmethod
def send(message: str, user: 'User'):
pass
# 具体中介者 - 聊天室
class ChatRoom(Mediator):
def __init__(self):
self.users = []
def add_user(self, user: 'User'):
self.users.append(user)
user.mediator = self
def send(self, message: str, user: 'User'):
for u in self.users:
if u != user:
u.receive(message)
# 抽象同事类
class Colleague(ABC):
mediator: Mediator = None
@abstractmethod
def send(self, message: str):
pass
@abstractmethod
def receive(self, message: str):
pass
# 具体同事类 - 用户
class User(Colleague):
def __init__(self, name: str):
self.name = name
def send(self, message: str):
print(f"{self.name}: 发送消息 -> {message}")
self.mediator.send(message, self)
def receive(self, message: str):
print(f"{self.name}: 收到消息 -> {message}")
# 创建聊天室
chat_room = ChatRoom()
# 创建用户并加入聊天室
alice = User("Alice")
bob = User("Bob")
chat_room.add_user(alice)
chat_room.add_user(bob)
# 用户发送消息
alice.send("你好 Bob!")
bob.send("嗨 Alice,很高兴见到你!")
4. 装饰模式
-
Decorator Pattern:在运行时给一个对象添加额外的行为或责任,而无需修改其结构。
-
使用python的装饰器机制即可
5. 单例模式
5.1 基础概念
-
单例:一个类在在全局只有一个对象
-
有利于对函数和数据的全局统一管理
5.2 实现方法
5.2.1 利用注册表
class Test:
def __init__(self, arg):
self.arg = arg
@staticmethod
def get_instance(arg):
global_vars = globals()
if "__Test_instance__" in global_vars:
return global_vars["__Test_instance__"]
else:
instance = Test(arg)
global_vars["__Test_instance__"] = instance
return instance
if __name__ == "__main__":
test1 = Test.get_instance("test1")
6. 克隆模式
-
又称为原型模式(Prototype Pattern)
在类中提供一个克隆本实例的方法
-
框架
from copy import deepcopy class Prototype: def clone(self): return deepcopy(self)
-
重点关注点应该在浅拷贝和深拷贝
浅拷贝:只拷贝指针(python中为引用)
深拷贝:开辟新的内存空间,复制数据
7. 职责模式
7.1 基础知识
-
又称责任链模式(Chain of Responsibility Pattern),构成要素
-
请求(Request):发送者到请求者的消息
-
发送者(Sender):消息发送者
-
接收者(Receiver):消息接受者,也是第一个处理者。每个接收者包含对下一个接收者的引用,形成一个链
-
处理者(Concrete Handlers):根据条件决定处理请求还是将请求传给下一个处理者
graph LR Sender --Request--> A["Receiver(Handler0)"] A --> Handler1 Handler1 --"..."--> Handlern
-
-
要点
- 实现了接收者和处理者之间的解耦
- 发送者只需要知道消息接受者是谁即可,不需要知道具体的处理链
-
典型应用:流程审批
7.2 代码框架
注意:Handler链一定是单链
class HandlerBase:
def __init__(self, name):
self.next_handler = None
def set_next_handler(self, next_handler):
self.next_handler = next_handler
def handle(self, request):
pass
class Handler1(HandlerBase):
def __init__(self, name):
super().__init__(name)
def handle(self, request):
if request == 1:
print("Handler1 handled the request")
if self.next_handler:
self.next_handler.handle(request)
class Handler2(HandlerBase):
def __init__(self, name):
super().__init__(name)
def handle(self, request):
if request == 2:
print("Handler2 handled the request")
if self.next_handler:
self.next_handler.handle(request)
class DefaultHandler(HandlerBase):
def __init__(self, name):
super().__init__(name)
def handle(self, request):
print("This is the default handler")
class Sender:
def __init__(self, name, receiver) -> None:
self.name = "Sender"
self.receiver = receiver
def send_request(self, request):
# 发送者只需关注是谁来接收这条消息
self.receiver.handle(request)
if __name__ == "__main__":
handler1 = Handler1("Handler1")
handler2 = Handler2("Handler2")
default_handler = DefaultHandler("DefaultHandler")
handler1.set_next_handler(handler2)
handler2.set_next_handler(default_handler)
sender = Sender("Sender", handler1)
sender.send_request(1)
sender.send_request(2)
sender.send_request(3)
8. 代理模式
8.1 基础知识
-
用户 --> 代理 --> 真正对象
-
代理(Proxy或Surrogate)模式
- 使用一个额外的间接层来支持分散的、可控的、智能的访问
- 增加一个包装来保护真正对象
-
在实际使用上的现实意义在于
- 向用户屏蔽了技术细节
- 技术细节的变动不会影响用户的使用习惯,因为用户访问的是代理
8.2 代码框架
- Subject(主题)接口:这是真实对象和代理对象共同遵循的一个接口,使得可以在任何时候用真实对象替换代理对象或者反之。
- RealSubject(真实主题)类:实现了Subject接口,并包含实际的业务逻辑。
- Proxy(代理)类:也实现了Subject接口,并且包含一个RealSubject对象的引用,代理对象可以在请求到达真实对象之前或之后执行一些操作。
class Subject:
"""
定义了RealSubject和Proxy共有的公共接口。
"""
def request(self):
pass
class RealSubject(Subject):
"""
包含了真实的请求。
"""
def request(self):
print("RealSubject handles request.")
class Proxy(Subject):
"""
代理类含有一个RealSubject的实例,而且提供与RealSubject相同的接口。
"""
def __init__(self, subject):
self.real_subject = subject
def request(self):
print("Proxy pre-processing.")
self.real_subject.request()
print("Proxy post-processing.")
9. 外观模式
- Facade Pattern:对整个复杂系统封装出简单接口,供用户使用
- 向用户屏蔽系统内部细节,降低系统内部和用户代码的耦合程度
- 并不存在通用的代码框架
10. 迭代模式
- Iterator Pattern:提供了一种方法来访问一个聚合对象(如列表、集合等)中的元素,而无需暴露该对象的底层表示。
- 直接使用python中迭代器或生成器即可
11. 组合模式
11.1 基础概念
- Composite Pattern:将系统设计成”整体-部分“(复合体-组件)的树状结构
- **Component(组件)和Composite(复合体/容器)**均实现了某个特定接口,比如run()
- 用户可不再区分组件和复合体的使用方式,直接调用run()即可
- Composite可以作为Component被组合,因此会形成树状结构
11.2 代码框架
class ComponentBase:
def __init__(self):
self.name = "Component"
def is_composite(self):
return False
def operation(self):
return self.name
class CompositeBase(ComponentBase):
def __init__(self):
self.children = []
def add(self, component):
self.children.append(component)
def remove(self, component):
self.children.remove(component)
def is_composite(self):
return True
def operation(self):
results = []
for child in self.children:
results.append(child.operation())
return f"{self.name}({'+'.join(results)})"
12. 构建模式
12.1 基础概念
-
builder pattern,又称建造者模式或生成者模式
- 将构造出的对象和构造过程分离,实现同一构造过程的复用
-
三个要素:
- Product(产品)
- Builder(构建者)
- BuilderManager(构建者管理)
-
未发现和工厂方法模式有什么实际上的区别。
12.2 代码框架
class ProductBase:
def __init__(self, name):
self.name = name
def func(self):
pass
class Product1(ProductBase):
def __init__(self, name, price):
super().__init__(name)
self.price = price
def func(self):
print('Product1 func')
class ProductBuilderBase:
def __init__(self):
self.product = None
def build(self):
pass
class Product1Builder(ProductBuilderBase):
def __init__(self):
super().__init__()
def build(self):
return Product1('Product1', 100)
class BuilderManager:
def __init__(self):
self.product1_builder = Product1Builder()
def build_product1(self):
return self.product1_builder.build()
product2
可以参照product1
的流程添加- 用户只需访问
BuilderManager
13. 适配模式
13.1 基本概念
-
Wrapper,包装模式,变压器模式:将一个对象进行包装或者转换,使其符合某种指定的接口
- 例如:HDMI-VGI的转换器
-
要素:
- Target(目标):定义客户端使用的与领域相关的接口。
- Adaptee(适配者):包含一些有用的业务逻辑,但是它的接口不符合
Target
的要求。适配器模式的核心在于创建一个适配器来解决Adaptee
和Target
之间的接口不匹配问题。 - Adapter(适配器):适配器包含
Adaptee
的实例,并且实现了Target
接口,从而作为Target
与Adaptee
之间的桥梁。
-
两种实现模式:
- 继承模式:Adapter 继承自 Adaptee
- 组合模式(推荐):Adaptee 对象是 Adapter的一个成员对象
13.2 代码框架
(组合模式)
class Target:
""" 目标接口 """
def request(self):
print("普通请求")
class Adaptee:
""" 适配者类,拥有不同的接口 """
def specific_request(self):
print("特定请求")
class Adapter:
""" 适配器类,通过组合包含适配者类的实例,并提供与目标相同的接口 """
def __init__(self, adaptee: Adaptee):
self._adaptee = adaptee
def request(self):
# 调用适配者的方法
self._adaptee.specific_request()
def client_code(target):
"""
客户端代码,只关心目标接口
"""
target.request()
if __name__ == "__main__":
# 创建适配者对象
adaptee = Adaptee()
# 创建适配器对象,并传入适配者对象
adapter = Adapter(adaptee)
# 客户端代码使用适配器
client_code(adapter)
14. 策略模式
14.1 基本概念
-
Strategy Pattern:定义一系列算法,将每个算法都封装起来,并且使它们之间可以相互替换。
-
三要素:
- Context(上下文):面向用户使用,屏蔽上层应用对策略的直接访问。
- Strategy (基类):定义统一的接口
- Concrete Strategy(具体策略):继承自Strategy基类的子类,具体算法
访问顺序为
Client --> Context --> Strategy
14.2 代码框架
from abc import ABC, abstractmethod
class StrategyBase(ABC):
@abstractmethod
def execute(self):
pass
class StrategyA(StrategyBase):
def __init__(self, name) -> None:
self._name = name
def execute(self):
print(f"StrategyA: {self._name}")
class StrategyB(StrategyBase):
def __init__(self, name) -> None:
self._name = name
def execute(self):
print(f"StrategyB: {self._name}")
class Context:
def __init__(self, strategy: StrategyBase) -> None:
self._strategy = strategy
def execute(self):
self._strategy.execute()
if __name__ == "__main__":
context = Context(StrategyA("A"))
context.execute()
context = Context(StrategyB("B"))
context.execute()
15. 工厂模式
简单工厂模式 --> 工厂方法模式 --> 抽象工厂模式
15.1 简单工厂模式
15.1.1 基础概念
-
Simple Factory Pattern,又称为静态工厂
- 通过if-else进行条件判断,确定创建哪个对象
-
最简单的工厂模式
-
推荐"字典工厂":在python中,dict的key确定创建哪个对象
{ "class1": Class1, "class2": Class2, }
使用时
def func(name): cls = cls_dict[name] return cls()
15.1.2 代码框架
典型方法
# 抽象产品
class Shape(ABC):
@abstractmethod
def draw(self):
pass
# 具体产品
class Circle(Shape):
def draw(self):
return "Drawing a circle..."
class Rectangle(Shape):
def draw(self):
return "Drawing a rectangle..."
class Square(Shape):
def draw(self):
return "Drawing a square..."
# 工厂类
class ShapeFactory:
def create_shape(self, shape_type):
if shape_type == "Circle":
return Circle()
elif shape_type == "Rectangle":
return Rectangle()
elif shape_type == "Square":
return Square()
else:
raise ValueError("Invalid shape type")
15.2 工厂方法模式
15.2.1 基础概念
- 相比于简单工厂,多了工厂基类。每个工厂子类继承自工厂基类,并只负责一个产品的创建
- 一个类的实例化延迟到工厂子类
- 未理解其用途和价值
15.2.2 代码框架
# Product
class Graphic:
def render(self):
raise NotImplementedError
class Circle(Graphic):
def render(self):
return "Rendering a circle..."
class Rectangle(Graphic):
def render(self):
return "Rendering a rectangle..."
# Factory
class GraphicFactory:
def create_graphic(self) -> Graphic:
raise NotImplementedError
class CircleFactory(GraphicFactory):
def create_graphic(self) -> Graphic:
return Circle()
class RectangleFactory(GraphicFactory):
def create_graphic(self) -> Graphic:
return Rectangle()
# client
def client_code(factory: GraphicFactory):
graphic = factory.create_graphic()
print(graphic.render())
if __name__ == "__main__":
circle_factory = CircleFactory()
client_code(circle_factory)
circle = Circle() # 直接初始化,不好么?
15.3 抽象工厂模式
15.3.1 基础概念
-
针对多种分类的产品或具有二级分类的产品
-
将产品本身和产品构造进行解耦,可在构造部分进行复杂设计
一个工厂可以构造多种产品
15.3.2 应用案例
from abc import ABC, abstractmethod
# 抽象产品
class RenderEngine(ABC):
@abstractmethod
def render(self):
pass
class ExportFormat(ABC):
@abstractmethod
def export(self, format):
pass
# 具体产品
class OpenGL(RenderEngine):
def render(self):
return "Rendering with OpenGL..."
class DirectX(RenderEngine):
def render(self):
return "Rendering with DirectX..."
class SVGExporter(ExportFormat):
def export(self, format):
return f"Exporting to {format} format"
class PNGExporter(ExportFormat):
def export(self, format):
return f"Exporting to {format} format"
# 抽象工厂
class GraphicFactory(ABC):
@abstractmethod
def create_render_engine(self) -> RenderEngine:
pass
@abstractmethod
def create_export_format(self) -> ExportFormat:
pass
# 具体工厂
class OpenGLFactory(GraphicFactory):
def create_render_engine(self) -> RenderEngine:
return OpenGL()
def create_export_format(self) -> ExportFormat:
return SVGExporter()
class DirectXFactory(GraphicFactory):
def create_render_engine(self) -> RenderEngine:
return DirectX()
def create_export_format(self) -> ExportFormat:
return PNGExporter()
# 客户端
def client_code(factory: GraphicFactory):
render_engine = factory.create_render_engine()
export_format = factory.create_export_format()
print(render_engine.render())
print(export_format.export("SVG"))
if __name__ == "__main__":
# 使用示例
opengl_factory = OpenGLFactory()
client_code(opengl_factory)
directx_factory = DirectXFactory()
client_code(directx_factory)
16. 命令模式
16.1 基本概念
-
Command Pattern:将请求(命令)封装成一个对象,实现请求发送者和执行者(接受者)之间进行解耦
-
四要素:
- 命令(Command):定义命令。
- 接收者(Receiver):接收并执行该命令。
- 调用者(Invoker):接收来自用户的命令,与用户进行交互。
- 用户(Client):命令的发送者
-
宏命令
理解为组合命令即可
16.2 代码框架
16.2.1 简单版
from abc import ABC, abstractmethod
# define the command interface and the receiver interface
class CommandBase(ABC):
@abstractmethod
def execute(self):
pass
class ReceiverBase(ABC):
@abstractmethod
def process(self):
pass
# define the concrete command and receiver
class ChatCommand(CommandBase):
def __init__(self, chat):
self.chat = chat
def execute(self):
self.chat.process('Hello World!')
class ChatReceiver(ReceiverBase):
def process(self, message):
print(f"ChatReceiver: {message}")
class Invoker:
def __init__(self):
self.command = None
def set_command(self, command, receiver=None):
# bind the command with the receiver
if "chat" in command:
receiver = ChatReceiver() if receiver is None else receiver
command = ChatCommand(receiver)
self.command = command
def execute(self):
self.command.execute()
if __name__ == "__main__":
invoker = Invoker()
invoker.set_command("chat")
invoker.execute()
16.2.2 宏命令版
# omit the CommandBase, ReceiverBase, ChatCommand, ChatReceiver
# define the concrete command and receiver
class CookCommand(CommandBase):
def __init__(self, chat):
self.chat = chat
def execute(self):
self.chat.process('Cooking')
class CookReceiver(ReceiverBase):
def process(self, message):
print(f"CookReceiver: {message}")
# macro command
class MacroCommand(CommandBase):
def __init__(self, commands):
self.commands = commands
def add_command(self, command):
self.commands.append(command)
def remove_command(self, command):
self.commands.remove(command)
def execute(self):
for command in self.commands:
command.execute()
class Invoker:
def __init__(self):
self.command = None
def set_command(self, command, receiver=None):
# bind the command with the receiver
if "chat" == command:
receiver = ChatReceiver() if receiver is None else receiver
command = ChatCommand(receiver)
if "cook&chat" == command:
cook_receiver = CookReceiver()
chat_receiver = ChatReceiver()
command = MacroCommand([CookCommand(chat_receiver), ChatCommand(chat_receiver)])
self.command = command
def execute(self):
self.command.execute()
if __name__ == "__main__":
invoker = Invoker()
invoker.set_command("chat")
invoker.execute()
17. 备忘模式
17.1 基本概念
-
Memento Pattern:用于捕获一个对象的内部状态,并在不破坏封装性的前提下,将这些状态存储起来,以便之后可以恢复到之前的状态
- 针对有需要包保存/回复状态的框架,如快照,数据回滚等
-
三要素:
- Originator(原始发起者):这个类负责创建一个备忘录来记录它的内部状态。当需要恢复状态的时候,它会从备忘录中获取信息。
- Memento(备忘录):这个对象用来存储发起者的内部状态。
- 可备份一组属性
- Caretaker(管理者):这个类用来管理备忘录对象。
- 可管理多个备忘录
-
三要素之间的关系:
- Memento只负责存储状态
- Originator负责创建memento和从memento中恢复的两个动作实现
- memento创建后的管理,以及恢复时向originator提供目标memento,由Caretaker负责
此时满足了“职责分离”原则
17.2 代码框架
from copy import deepcopy
class Memento:
def __init__(self, state):
self._state = deepcopy(state)
def get_state(self):
return deepcopy(self._state)
class Originator:
def __init__(self):
self._state = None
# do something to change the state
def set_state(self, state):
self._state = state
def save(self):
return Memento(self._state)
def restore(self, memento):
self._state = memento.get_state()
class Caretaker:
def __init__(self):
# use a dict when you want to save multiple originator states
self._mementos = []
def add_memento(self, memento):
self._mementos.append(memento)
def get_memento(self, index=-1):
return self._mementos[index]
if __name__ == "__main__":
originator = Originator()
caretaker = Caretaker()
originator.set_state("state1")
# save the state
caretaker.add_memento(originator.save())
print(originator._state)
# restore the state
originator.restore(caretaker.get_memento(-1))
print(originator._state)
18. 享元模式
18.1 基础概念
-
Flyweight Pattern,能共享的对象是轻量级(细粒度的)的(因为需要共享)
-
对于可共享的对象而言,状态分为两种
- 内部状态(Intrinsic State):可以共享的,存在对象内部的,不会随环境而改变的
- 外部状态(Extrinsic State):每个对象独有的,存在外部的,随环境而改变
class Colour: def __init__(self, colour): # Intrinsic State self._colour = colour def print_with_colour(self, text): # text is Extrinsic State print(f"{self._colour}{text}\033[0m") if __name__ == "__main__": red = Colour("\033[31m") red.print_with_colour("Hello, World!")
-
享元工厂(FlyweightFactory),理解成字典工厂即可
- 负责管理享元对象
18.2 代码框架
class Flyweight:
def __init__(self, intrinsic_state):
self.__intrinsic_state = intrinsic_state
def operation(self, extrinsic_state):
print(f'Intrinsic state: {self.__intrinsic_state}')
print(f'Extrinsic state: {extrinsic_state}')
class FlyweightFactory:
def __init__(self):
self.__flyweights = {}
def get_flyweight(self, intrinsic_state):
if intrinsic_state not in self.__flyweights:
self.__flyweights[intrinsic_state] = Flyweight(intrinsic_state)
return self.__flyweights[intrinsic_state]
if __name__ == "__main__":
factory = FlyweightFactory()
flyweight = factory.get_flyweight('intrinsic state')
flyweight.operation('extrinsic state')
19. 访问模式
19.1 基础概念
- Visitor Pattern,将数据结构和操作(算法)解耦。可在不改变数据结构的前提下,增加新操作。
- 三要素:
- 访问者 Visitor:操作
- 数据节点 DataNode:数据对象
- 对象结构 ObjectStructure:数据对象的容器
19.2 代码框架
from abc import ABC, abstractmethod
class DataNode(ABC):
@abstractmethod
def accept(self, visitor):
pass
class Visitor(ABC):
@abstractmethod
def visit(self, node):
pass
class ChatNode(DataNode):
def __init__(self, name):
self.name = name
def accept(self, visitor):
visitor.visit(self)
class CookNode(DataNode):
def __init__(self, name):
self.name = name
def accept(self, visitor):
visitor.visit(self)
class ChatVisitor(Visitor):
def visit(self, node):
print(f"ChatVisitor visiting {node.name}")
class ObjectStructure:
def __init__(self):
self.nodes = []
def add_node(self, node):
self.nodes.append(node)
def visit(self, visitor):
for node in self.nodes:
node.accept(visitor)
if __name__ == "__main__":
chat = ChatNode("chat")
cook = CookNode("cook")
object_structure = ObjectStructure()
object_structure.add_node(chat)
object_structure.add_node(cook)
chat_visitor = ChatVisitor()
object_structure.visit(chat_visitor)
注意:依靠访问模式,可实现双分派。未曾见到实际使用案例。
class DataNode:
def accept(self, visitor):
# 通过调用访问者的哪个visit方法,实现第二次分派
visitor.visit_a(self)
class Visitor():
def visit_a(self, node):
pass
def visit_b(self, node):
pass
class ObjectStructure:
def __init__(self):
self.nodes = []
def add_node(self, node):
self.nodes.append(node)
def visit(self, visitor):
# 通过调用哪个node的accept方法,实现第一次分派
self.nodes[0].accept(visitor)
20 模板模式
-
模板模式(Template Method Pattern):定义了一个算法的骨架,而将一些步骤延迟到子类中实现。
- 先写抽象基类,其中定义关键接口
- 后写继承自基类的具体实现
抽象积累为后续的所有实现,定义了统一的接口
21 桥接模式
21.1 基本概念
-
Bridge Pattern:抽象和实现分离,使两者可独立变化。
这个定义就很抽象,甚至误导。
-
实操上是
- 先把代码框架按模块和层级划分好
- 并且用抽象基类把这个框架搭起来,把重要的接口定义好
桥接模式的定义和抽象基类代码框架的概念上的关系是
- 抽象:最大(最外层)的那个抽象基类
- 实现:最大的抽象基类的子模块(尽管也是抽象基类)
-
适用:推荐复杂代码框架都这么干
21.2 代码样例
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def draw(self):
pass
class Color(ABC):
@abstractmethod
def apply_color(self):
pass
class Red(Color):
def apply_color(self):
return "Red color"
class Green(Color):
def apply_color(self):
return "Green color"
class Circle(Shape):
def __init__(self, color):
self._color = color
def draw(self):
print(f"Drawing {self._color.apply_color()} circle")
class Square(Shape):
def __init__(self, color):
self._color = color
def draw(self):
print(f"Drawing {self._color.apply_color()} square")
if __name__ == "__main__":
red_color = Red()
green_color = Green()
red_circle = Circle(red_color)
red_square = Square(red_color)
green_circle = Circle(green_color)
green_square = Square(green_color)
red_circle.draw() # 输出: Drawing Red color circle
red_square.draw() # 输出: Drawing Red color square
green_circle.draw() # 输出: Drawing Green color circle
green_square.draw() # 输出: Drawing Green color square
对于桥接模式定义而言,shape是抽象,Color是实现
22 解释模式
-
Interpreter Pattern:用于处理语言语法或表达式的解析问题
-
四要素:
- Abstract Expression (抽象表达式):抽象类或接口,定义接口
interpret()
。 - Terminal Expression (终结符表达式):语法中最小的单元逻辑
- Non-terminal Expression (非终结符表达式):语法中每一条规则对应一个非终结符表达式
- Context (上下文):包含外部信息或数据,这些信息或数据可能会影响表达式的解释。
对于
a + b + c
而言,a
就是终结符表达式,+
就是非终结符表达式,在解析该字符串含义时产生的中间信息,保存在上下文中 - Abstract Expression (抽象表达式):抽象类或接口,定义接口
-
除非要自己构建某种语法,否则这种模式用不上
附录A:分派
A.1 概念
(此处为根据网上资料汇总得到,有待查证)
-
多态(Polymorphism,java中似乎翻译成宗量)依赖分派(Dispatch)实现
- 分派:是选择并执行一个方法的过程(选哪个函数执行)
-
分派类型可按以下角度进行划分
- 分派时间:静态分派(Static Dispatch),动态分派(Dynamic Dispatch)
- 分派依据:单分派(Single Dispatch),多分派(Multiple Dispatch)
-
静态分派:在编译期确定调用哪个方法
- 例如,C++中函数重载(Overload),根据不同参数类型和数量进行分派
-
动态分派:在运行期确定调用哪个方法
- 例如,C++中虚函数的重写(Override),根据对象的实际类型来分派
-
单分派:根据一个参数类型(通常是接受者类型)来分派
-
多分派:根据多个参数类型来分派
- Common Lisp 或者 Haskell 某些语言的特性
- 似乎特指运行时,否则C应该也算多分派了,通常认为C是单分派
C++中的重载支持静态多分派,而虚函数支持动态单分派
A.2 Python与分派
在python中讨论分派,意义是不大的
A.2.1 单分派
实现python函数重载
from functools import singledispatch
@singledispatch
def process(arg):
raise NotImplementedError("Unsupported type")
@process.register(int)
def _(arg):
print(f"Processing integer: {arg}")
@process.register(str)
def _(arg):
print(f"Processing string: {arg}")
# 测试
process(5) # 输出: Processing integer: 5
process("hello") # 输出: Processing string: hello
A.2.2 (动态)多分派
使用第三方库
pip install multipledispatch
from multipledispatch import dispatch
@dispatch(int, int)
def add(a, b):
print(f"Adding two integers: {a} + {b} = {a + b}")
@dispatch(str, str)
def add(a, b):
print(f"Concatenating strings: {a} + {b} = {a + b}")
# 测试
add(5, 3) # 输出: Adding two integers: 5 + 3 = 8
add("hello", " world") # 输出: Concatenating strings: hello + 世界 = hello world
附录B:Python中的copy
- python官方关于copy的解释:https://docs.python.org/zh-cn/3/library/copy.html
B.1 浅拷贝
-
浅拷贝 (Shallow Copy)
- 会创建一个新对象,并**将原对象的引用插入到新对象中**(核心点)。
- 对于不可变类型(如字符串、数字等),这意味着新旧对象中的这些值是完全独立的;
- 但对于可变类型(如列表、字典等),原始对象的改变会影响浅拷贝的对象,因为它们共享相同的元素。
- 类也在此情况中
-
可变类型的样例
from copy import copy, deepcopy original_list = [[1, 2], [3, 4]] shallow_copied_list = copy(original_list) # 情况1:修改原始列表中的子列表 original_list[0].append(5) print("Original List:", original_list) print("Shallow Copied List:", shallow_copied_list) # 情况2: 修改原始列表 original_list.append([6, 7]) print("Original List:", original_list) print("Shallow Copied List:", shallow_copied_list)
输出结果
Original List: [[1, 2, 5], [3, 4]] Shallow Copied List: [[1, 2, 5], [3, 4]] Original List: [[1, 2, 5], [3, 4], [6, 7]] Shallow Copied List: [[1, 2, 5], [3, 4]]
-
类的浅拷贝
from copy import copy, deepcopy class A: def __init__(self, x): self.x = x self.li = [1,2,3] a = A(1) b = copy(a) b.x = 2 b.li[0] = 4 print(a.x) print(a.li)
输出
1 [4, 2, 3]
B.2 深拷贝
-
Deep Copy
- 不仅会创建新对象,还会递归地拷贝所有嵌套的对象。
这样,新对象就完全独立于原对象,对新对象所做的任何修改都不会影响到原对象。
附录C: 设计模式的分类
C.1 行为型模式
这类模式关注的是算法与对象间的基本行为。它们帮助定义对象之间的责任分配,或者如何进行通信。
- 模板方法模式(Template Method)
- 命令模式(Command)
- 责任链模式(Chain of Responsibility)
- 解释器模式(Interpreter)
- 迭代器模式(Iterator)
- 中介者模式(Mediator)
- 备忘录模式(Memento)
- 观察者模式(Observer)
- 状态模式(State)
- 策略模式(Strategy)
- 访问者模式(Visitor)
C.2 结构型模式
这些模式关注于简化系统的设计通过提供一个简单的接口来掩盖复杂的子系统。它们通常处理类或对象的组合,并且经常用于创建更灵活的类结构。
- 适配器模式(Adapter)
- 桥接模式(Bridge)
- 组合模式(Composite)
- 装饰模式(Decorator)
- 外观模式(Facade)
- 享元模式(Flyweight)
- 代理模式(Proxy)
C.3 创建型模式
这类模式提供了一种在创建对象时隐藏创建逻辑的方式,而不是使用直接的对象实例化。它们帮助将对象的创建与其使用解耦。
- 单例模式(Singleton)
- 原型模式(Prototype): 克隆模式
- 工厂方法模式(Factory Method):第15.2节
- 抽象工厂模式(Abstract Factory):第15.3节
- 构建者模式(Builder)