# Python学习常用设计模式 **Repository Path**: suni1024/python-design-pattern ## Basic Information - **Project Name**: Python学习常用设计模式 - **Description**: python的常用设计模式 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-10-27 - **Last Updated**: 2025-11-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: 学习完成 ## README # Python 设计模式 ## 创建型模式 ### 1、简单工厂模式 ```python # encoding: utf-8 # 项目名称: 常用设计模式 # @File : 003-简单工厂模式.py # @Author: sun hao # @Desc : # @Date : 13:56 2024/10/29 from abc import ABCMeta, abstractmethod class Payment(metaclass=ABCMeta): """ 抽象支付类,定义了支付接口。 """ @abstractmethod def pay(self, money): pass class Alipay(Payment): """ 支付宝支付类。 """ def __init__(self, use_huabei=False): self.use_huabei = use_huabei def pay(self, money): print("支付宝") if self.use_huabei: print(f"花呗支付{money}元") else: print(f"余额支付{money}元") class WeChatPay(Payment): """ 微信支付类。 """ def pay(self, money): print("微信") print(f"支付{money}元") class PaymentFactory: """ 支付工厂类,用于创建不同类型的支付对象。 """ def create_payment(self, payment_type): if payment_type == "alipay": return Alipay() elif payment_type == "alipay-huabei": return Alipay(use_huabei=True) elif payment_type == "wechatpay": return WeChatPay() else: raise ValueError(f'No such payment named: {payment_type}') # 客户端使用 pf = PaymentFactory() p = pf.create_payment("wechatpay") p.pay(1024) ``` #### 优点: - 隐藏了对象创建的实现细节 - 客户端不需要修改代码 #### 缺点: - 违反了单一职责原则,将创建逻辑几种放到一个工厂类中 - 当添加新产品时,需要修改工厂类代码,违反了开闭原则 ### 2、工厂方法模式 ```python # encoding: utf-8 # 项目名称: 常用设计模式 # @File : 004-工厂方法模式.py # @Author: sun hao # @Desc : # @Date : 14:14 2024/10/29 from abc import ABCMeta, abstractmethod class Payment(metaclass=ABCMeta): """ 抽象支付类,定义了支付接口。 """ @abstractmethod def pay(self, money): pass class Alipay(Payment): """ 支付宝支付类。 """ def __init__(self, use_huabei=False): self.use_huabei = use_huabei def pay(self, money): print("支付宝") if self.use_huabei: print(f"花呗支付{money}元") else: print(f"余额支付{money}元") class WeChatPay(Payment): """ 微信支付类。 """ def pay(self, money): print("微信") print(f"支付{money}元") class BankPay(Payment): """ 银行卡支付 """ def pay(self, money): print("银行卡") print(f"支付{money}元") class PaymentFactory(metaclass=ABCMeta): @abstractmethod def create_payment(self): pass class AlipayFactory(PaymentFactory): def create_payment(self): return Alipay() class HuabeiAliapyFactory(PaymentFactory): def create_payment(self): return Alipay(use_huabei=True) class WeChatPayFactory(PaymentFactory): def create_payment(self): return WeChatPay() class BankPayFactory(PaymentFactory): def create_payment(self): return BankPay() pf = WeChatPayFactory() p = pf.create_payment() p.pay(1014) ``` #### 优点: - 每个具体产品都对应一个具体工厂类,不需要修改工厂代码 - 隐藏了对象创建的实现细节 #### 缺点: - 每增加一个具体产品类,就必须增加一个相应的具体工厂类 ### 3、抽象工厂模式 ```python # encoding: utf-8 # 项目名称: 常用设计模式 # @File : 004-工厂方法模式.py # @Author: sun hao # @Desc : # @Date : 14:14 2024/10/29 from abc import ABCMeta, abstractmethod class Payment(metaclass=ABCMeta): """ 抽象支付类,定义了支付接口。 """ @abstractmethod def pay(self, money): pass class Alipay(Payment): """ 支付宝支付类。 """ def __init__(self, use_huabei=False): self.use_huabei = use_huabei def pay(self, money): print("支付宝") if self.use_huabei: print(f"花呗支付{money}元") else: print(f"余额支付{money}元") class WeChatPay(Payment): """ 微信支付类。 """ def pay(self, money): print("微信") print(f"支付{money}元") class BankPay(Payment): """ 银行卡支付 """ def pay(self, money): print("银行卡") print(f"支付{money}元") class PaymentFactory(metaclass=ABCMeta): @abstractmethod def create_payment(self): pass class AlipayFactory(PaymentFactory): def create_payment(self): return Alipay() class HuabeiAliapyFactory(PaymentFactory): def create_payment(self): return Alipay(use_huabei=True) class WeChatPayFactory(PaymentFactory): def create_payment(self): return WeChatPay() class BankPayFactory(PaymentFactory): def create_payment(self): return BankPay() pf = WeChatPayFactory() p = pf.create_payment() p.pay(1014) ``` #### 优点: - 将客户端与类的具体实现相分离 - 每个工厂创建了一个完整的产品系列,使得易于交换产品系列 - 有利于产品的一致性(每个产品之间的约束关系) #### 缺点: - 难以支持新种类的(抽象)产品 ### 4、创建者模式 ```python from abc import ABCMeta, abstractmethod # 定义一个玩家类,包含玩家的各个部位属性 class Player: def __init__(self, face=None, body=None, arm=None, leg=None): # 初始化玩家的身体部位 self.face = face self.body = body self.arm = arm self.leg = leg def __str__(self): # 返回玩家的身体部位信息,方便打印输出 return f'{self.face},{self.body},{self.arm},{self.leg}' # 定义一个抽象的建造者类,规定了所有具体建造者必须实现的方法 class PlayerBuilder(metaclass=ABCMeta): @abstractmethod def build_face(self): pass @abstractmethod def build_body(self): pass @abstractmethod def build_arm(self): pass @abstractmethod def build_leg(self): pass # 具体建造者类 - 创建美女 class SexyGrilBuilder(PlayerBuilder): def __init__(self): # 每个具体的建造者类都需要创建一个Player实例 self.player = Player() def build_face(self): # 设置美女的脸型 self.player.face = "鹅蛋脸" def build_body(self): # 设置美女的身体特征 self.player.body = "身材苗条" def build_arm(self): # 设置美女的手臂特征 self.player.arm = "胳膊纤细" def build_leg(self): # 设置美女的腿部特征 self.player.leg = "大长腿" # 具体建造者类 - 创建野兽 class Monster(PlayerBuilder): def __init__(self): # 同样地,创建一个Player实例用于构建野兽对象 self.player = Player() def build_face(self): # 设置野兽的脸型 self.player.face = "国字脸" def build_body(self): # 设置野兽的身体特征 self.player.body = "身材魁梧" def build_arm(self): # 设置野兽的手臂特征 self.player.arm = "胳膊粗壮" def build_leg(self): # 设置野兽的腿部特征 self.player.leg = "大长腿" # 控制器类,负责调用具体的建造者来构建玩家对象 class PlayerDirector: def build_player(self, builder): # 调用具体的建造者方法,按特定顺序构建玩家对象的不同部位 builder.build_body() builder.build_face() builder.build_arm() builder.build_leg() # 构建完成后返回完整的玩家对象 return builder.player # 客户端代码 builder = Monster() # 创建一个野兽建造者对象 director = PlayerDirector() # 创建一个导演对象 p = director.build_player(builder) # 导演指挥建造者构建玩家对象 print(p) # 输出构建好的玩家对象的信息 ``` > 建造者模式与抽象工厂模式类似,也用来创建复杂对象。 > 主要区别是建造者模式着重于一步步构造一个复杂对象,而抽象该工厂模式着重于多个系列的产品对象 #### 优点: - 隐藏了一个产品的内部结构和装配过程 - 将构造代码与表示代码分开 - 可以对构造过程进行更精细的控制 ### 5、单例模式 ```python class Singleton: _instance = None def __new__(cls, *args, **kwargs): if cls._instance is None: cls._instance = super(Singleton, cls).__new__(cls) cls._instance.initialized = False # 初始化标志 return cls._instance class MyClass(Singleton): def __init__(self, a): if not self.initialized: self.a = a self.initialized = True a1 = MyClass(100) a2 = MyClass(200) print(a1.a) # 输出: 100 print(a2.a) # 输出: 100 print(id(a1), id(a2)) # 输出: 相同的内存地址 ``` #### 内容: ```tex 保证一个类只有一个实例,并提供一个访问它的全局访问点 ``` #### 角色: ``` 单例(Singleton) ``` #### 优点: - 对唯一实例的受控访问 - 单例相当于全局变量,但防止了命名控件被污染 #### 使用场景 单例模式是一种常用的软件设计模式,确保一个类只有一个实例,并提供一个全局访问点。这种模式在多种场景中非常有用,特别是在需要全局共享资源或管理配置的情况下。以下是一些常见的使用场景: ##### 1. **配置管理** - **场景**: 应用程序需要从配置文件中读取配置信息,并在整个应用程序中共享这些配置。 - **优点**: 单例模式确保配置信息只加载一次,并且所有需要配置的地方都能访问到同一个实例。 ```python class ConfigManager(Singleton): def __init__(self): if not self.initialized: self.config = self.load_config() self.initialized = True def load_config(self): # 模拟从文件中加载配置 return {'db_url': 'localhost', 'port': 5432} config = ConfigManager().config print(config) # 输出: {'db_url': 'localhost', 'port': 5432} ``` 2. **日志记录** - **场景**: 应用程序需要记录日志,并希望所有模块都能访问同一个日志记录器。 - **优点**: 单例模式确保日志记录器只初始化一次,并且所有模块都能使用同一个日志记录器。 ```python class Logger(Singleton): def __init__(self): if not self.initialized: self.log_file = open('app.log', 'a') self.initialized = True def log(self, message): self.log_file.write(message + '\n') self.log_file.flush() logger = Logger() logger.log('This is a log message.') ``` ##### 3. **数据库连接** - **场景**: 应用程序需要连接到数据库,并希望所有模块都能使用同一个数据库连接。 - **优点**: 单例模式确保数据库连接只建立一次,并且所有模块都能使用同一个连接。 ```python import sqlite3 class DatabaseConnection(Singleton): def __init__(self): if not self.initialized: self.connection = sqlite3.connect('app.db') self.cursor = self.connection.cursor() self.initialized = True def execute(self, query): return self.cursor.execute(query) db = DatabaseConnection() result = db.execute('SELECT * FROM users') for row in result: print(row) ``` ##### 4. **缓存管理** - **场景**: 应用程序需要缓存一些数据,并希望所有模块都能访问同一个缓存。 - **优点**: 单例模式确保缓存只初始化一次,并且所有模块都能使用同一个缓存。 ```python class CacheManager(Singleton): def __init__(self): if not self.initialized: self.cache = {} self.initialized = True def get(self, key): return self.cache.get(key) def set(self, key, value): self.cache[key] = value cache = CacheManager() cache.set('key1', 'value1') print(cache.get('key1')) # 输出: value1 ``` ##### 5. **线程池管理** - **场景**: 应用程序需要管理一组线程,并希望所有模块都能访问同一个线程池。 - **优点**: 单例模式确保线程池只初始化一次,并且所有模块都能使用同一个线程池。 ```python from concurrent.futures import ThreadPoolExecutor class ThreadPoolManager(Singleton): def __init__(self): if not self.initialized: self.pool = ThreadPoolExecutor(max_workers=5) self.initialized = True def submit_task(self, task): self.pool.submit(task) thread_pool = ThreadPoolManager() thread_pool.submit_task(lambda: print("Task executed")) ``` ##### 总结 单例模式适用于那些需要全局唯一实例并且希望避免重复初始化的场景。通过确保一个类只有一个实例,单例模式可以帮助管理资源、提高性能并简化代码。然而,需要注意的是,单例模式也有一些缺点,例如它可能会隐藏类之间的依赖关系,使得代码难以测试和维护。因此,在使用单例模式时应谨慎考虑其适用性和潜在的影响。 ## 结构型模式(7)种 ### 1、适配器模式 #### 内容:将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 #### 2种实现方式: ##### 类适配器:使用多继承 ##### 对象适配器:使用组合 ```python # encoding: utf-8 # 项目名称: 常用设计模式 # @File : 008-适配器模式.py # @Author: sun hao # @Desc : # @Date : 19:30 2024/10/29 from abc import ABCMeta, abstractmethod class Payment(metaclass=ABCMeta): @abstractmethod def pay(self, money): pass class Alipay(Payment): def pay(self, money): print("支付宝") print(f"支付{money}元") class WeChatPay(Payment): def pay(self, money): print("微信") print(f"支付{money}元") class BankPay: """ 新来一个银行卡支付,没有pay方法怎么搞? """ def cost(self, money): print("银行卡") print(f"支付{money}元") class AppleIphonePay: """ 新来一个苹果手机支付,没有pay方法怎么搞? """ def cost(self, money): print("苹果支付") print(f"支付{money}元") class HuaWeiPhonePay: """ 新来一个华为手机支付,没有pay方法怎么搞? """ def cost(self, money): print("华为支付") print(f"支付{money}元") p1 = Alipay() p1.pay(1024) # --------情况1,一个class对不上 使用多继承-------- class NewBankPay(Payment, BankPay): """ 写一个适配器类,继承 Payment 与 BankPay """ def pay(self, money): self.cost(money) print("类适配器,使用多继承模式") p2 = NewBankPay() p2.pay(1024) # --------情况2,多个class对不上 使用组合-------- class PaymentAdapter(Payment): def __init__(self, payment_type): self.payment_type = payment_type def pay(self, money): self.payment_type.cost(money) print("对象适配器,使用组合模式") p3 = PaymentAdapter(HuaWeiPhonePay()) p3.pay(1024) ``` #### 使用场景: - 想使用一个已存在的类,但是它的接口不符合你的要求 - (对象适配器)想使用一些已经存在的子类,但不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。 ### 2、桥接式 #### 内容: - 将一个事物的2个维度分离,让其都可以独立化 ```python # encoding: utf-8 # 项目名称: 常用设计模式 # @File : 009-桥模式.py # @Author: sun hao # @Desc : # @Date : 19:53 2024/10/29 from abc import ABCMeta, abstractmethod class Shape(metaclass=ABCMeta): def __init__(self, color): self.color = color @abstractmethod def draw(self): pass class Color(metaclass=ABCMeta): @abstractmethod def paint(self, shape): pass class Rectangle(Shape): name = "长方形" def draw(self): self.color.paint(self) class Circle(Shape): name = "圆形" def draw(self): self.color.paint(self) # 具体的颜色类 class Red(Color): def paint(self, shape1): print(f"绘制 {shape1.name},颜色为红色") class Blue(Color): def paint(self, shape1): print(f"绘制 {shape1.name},颜色为蓝色") # 创建形状对象并设置颜色 red_rectangle = Rectangle(Red()) blue_circle = Circle(Blue()) # 绘制形状 red_rectangle.draw() # 输出: 绘制 长方形,颜色为红色 blue_circle.draw() # 输出: 绘制 圆形,颜色为蓝色 ``` ### 3、组合模式 #### 使用场景: - 表示对象的 " 部分-整体",层次结构(特别是结构是递归的) - 希望用户忽略组合对象与单个对象的不同,用户统一地使用组合结构中的所有对象 #### 优点: - 定义了包含基本对象和组合对象的类层次结构 - 简化客户端代码,客户端可以一致的组合对象与单个对象 - 更容易增加新类型的组件 ```python # encoding: utf-8 # 项目名称: 常用设计模式 # @File : 010-组合模式.py # @Author: sun hao # @Desc : # @Date : 20:33 2024/10/29 from abc import ABCMeta, abstractmethod class Graphic(metaclass=ABCMeta): @abstractmethod def draw(self): pass class Point(Graphic): def __init__(self, x, y): self.x = x self.y = y def __str__(self): return f'(点:{self.x}, {self.y})' def draw(self): print(str(self)) class Line(Graphic): def __init__(self, p1, p2): self.p1 = p1 self.p2 = p2 def __str__(self): return f'(线段:{self.p1}, {self.p2})' def draw(self): print(str(self)) class Picture(Graphic): def __init__(self, iterable): self.children = [] for g in iterable: self.add(g) def add(self, graphic): self.children.append(graphic) def draw(self): print('----复合图形 S----') for g in self.children: g.draw() print('----复合图形 E----') p1 = Point(2, 3) l1 = Line(Point(3, 4), Point(4, 5)) l2 = Line(Point(1, 5), Point(2, 8)) pic1 = Picture([p1, l1, l2]) pic1.draw() # 示例2:用户界面组件 class UIComponent(metaclass=ABCMeta): @abstractmethod def render(self): pass class Button(UIComponent): def __init__(self, label): self.label = label def render(self): print(f"渲染按钮: {self.label}") class Panel(UIComponent): def __init__(self, title): self.title = title self.children = [] def add(self, component): self.children.append(component) def render(self): print(f"渲染面板: {self.title}") for child in self.children: child.render() # 创建UI组件 button1 = Button("按钮1") button2 = Button("按钮2") # 创建面板并添加组件 panel1 = Panel("面板1") panel1.add(button1) panel1.add(button2) # 渲染面板 panel1.render() # 示例3:文件系统浏览器 class FileSystemItem(metaclass=ABCMeta): @abstractmethod def display(self): pass class File(FileSystemItem): def __init__(self, name): self.name = name def display(self): print(f"显示文件: {self.name}") class Directory(FileSystemItem): def __init__(self, name): self.name = name self.children = [] def add(self, item): self.children.append(item) def display(self): print(f"显示目录: {self.name}") for child in self.children: child.display() # 创建文件和目录 file1 = File("文件1.txt") file2 = File("文件2.txt") dir1 = Directory("子目录1") dir1.add(file1) dir1.add(file2) # 创建根目录 root_dir = Directory("根目录") root_dir.add(dir1) # 显示文件系统结构 root_dir.display() ``` ### 4、装饰模式 ### 5、外观模式 #### 优点: - 减少系统相互依赖 - 提高了灵活性 - 提高了安全性 ```python # encoding: utf-8 # 项目名称: 常用设计模式 # @File : 011-外观模式.py # @Author: sun hao # @Desc : # @Date : 19:57 2024/11/04 class CPU: def run(self): print("cpu启动") def stop(self): print("cpu停止") class DISK: def run(self): print("disk启动") def stop(self): print("disk停止") class Memory: def run(self): print("Memory启动") def stop(self): print("Memory停止") class Computer: def __init__(self): self.cpu = CPU() self.disk = DISK() self.memory = Memory() def run(self): print('开机') self.cpu.run() self.disk.run() self.memory.run() def stop(self): print('关机') self.cpu.stop() self.disk.stop() self.memory.stop() # 客户端代码 HuaWeiPc = Computer() HuaWeiPc.run() # 开机 HuaWeiPc.stop() # 关机 ``` ### 6、享元模式 ### 7、代理模式 #### 内容: > 为其他对象提供一种代理以控制这个对象的访问 #### 应用场景: - 远程代理:为远程的对象提供代理 - 虚代理:根据需要创建很大的对象 - 保护代理:控制对原始对象的访问,用于对象有不同访问权限时 ```python # encoding: utf-8 # 项目名称: 常用设计模式 # @File : 012-代理模式.py # @Author: sun hao # @Desc : # @Date : 20:07 2024/11/04 from abc import ABCMeta, abstractmethod class Subject(metaclass=ABCMeta): @abstractmethod def get_content(self): pass def set_content(self, content): pass class RealSubject(Subject): def __init__(self, filename): # 我这里去打卡一个文件,把里面的内容取读取出来,并写入到content中 self.filename = filename print('读取文件内容') with open(self.filename, 'r', encoding='utf-8') as f: self.content = f.read() def get_content(self): # 通过 get_content 就可以知道我读取的内容了 return self.content def set_content(self, content): # 根据 新的content,重新打开文件,并写入新content with open(self.filename, 'w', encoding='utf-8') as f: f.write(content) # real_subject = RealSubject('012.txt') # 输出,读取的文件内容 # print(real_subject.get_content()) # # 修改文件内容 # new_content = "这是新的文件内容。\n" # real_subject.set_content(new_content) # # # 再次获取文件内容 # print("修改后的文件内容:") # print(real_subject.get_content()) # 如果用户读取了这个txt文件,但是什么也不做,如果文件很大,就直接占用了很大的内存空间 print('-----------------------虚代理--------------------------------------') # 虚代理 class VirtualProxy(Subject): def __init__(self, filename): self.filename = filename self.subj = None def get_content(self): if not self.subj: self.subj = RealSubject(self.filename) return self.subj.get_content() def set_content(self, content): if not self.subj: self.subj = RealSubject(self.filename) return self.subj.set_content(content) virtualProxy1 = VirtualProxy('012.txt') # 我如果下面的print 不执行,你会发现在控制台中看不到 读取文件内容 这个输出;这说明,运行到这里的时候,没有占用内容 print(virtualProxy1.get_content()) # 到这里,才会读取并打印输出 txt文件中的内容,才会占用内存 print('-----------------------保护代理--------------------------------------') # 保护代理 需要一个只有读,没有写的权限 class ProtectedProxy(Subject): def __init__(self, filename): self.subj = RealSubject(filename) def get_content(self): return self.subj.get_content() def set_content(self, content): raise PermissionError('无写入权限') # 保护代理,是没有虚代理功能的,它这里其实已经读取好了文件中的内容 ProtectedProxy1 = ProtectedProxy('012.txt') print(ProtectedProxy1.get_content()) ProtectedProxy1.set_content('1234') ``` ## 行为模式(11)种 ### 1、解释器模式 ### 2、责任链模式 #### 内容: > 让多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。 > 将这些对象连成一条链,并沿着这个链路传递该请求,一直到有一个对象处理它为止。 #### 使用场景: - 有多个对象可以处理一个请求,那个对象处理由运行决定 - 在不明确接收的情况下,向多个对象中的一个提交一个请求 #### 优点: - 降低耦合度:一个对象无需知道是其他哪一个对象处理其请求 ```python # encoding: utf-8 # 项目名称: 常用设计模式 # @File : 013-责任链模式.py # @Author: sun hao # @Desc : # @Date : 20:14 2024/11/05 from abc import ABCMeta, abstractmethod class Handler(metaclass=ABCMeta): @abstractmethod def handle_leave(self, day): pass class GeneralManager(Handler): def handle_leave(self, day): if day <= 10: print(f'总经理批准{day}天假期') else: print(f'总经理说:{day}天假期太久出来,你还是提桶跑路吧') class DepartmentManager(Handler): def __init__(self): self.next = GeneralManager() def handle_leave(self, day): if day <= 5: print(f'部门经理批准{day}天假期') else: print(f'{day}天假期太久了,部门经理批不了,往上报') self.next.handle_leave(day) class ProjectDirector(Handler): def __init__(self): self.next = DepartmentManager() def handle_leave(self, day): if day <= 3: print(f'技术主管批准{day}天假期') else: print(f'{day}天假期太久了,技术主管批不了,往上报') self.next.handle_leave(day) day = 4 user = ProjectDirector() user.handle_leave(day) ``` ### 3、命令模式 ### 4、迭代器模式 ### 5、中介者模式 ### 6、备忘录模式 ### 7、观察者模式(发布-订阅模式) #### 内容: > 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知,并自动更新。观察者模式又称为"发布-订阅"模式 ```python from abc import ABCMeta, abstractmethod # 抽象 观察者 也就是订阅者 class Observer(metaclass=ABCMeta): @abstractmethod def update(self, notice): # notice 参数是一个 Notice 类的对象 pass # 抽象 发布者 class Notice: def __init__(self): self.observers = [] # 初始化观察者列表 # 绑定观察者到发布者的列表中 def attach(self, obs): self.observers.append(obs) # 从发布者的观察者列表中移除观察者 def detach(self, obs): self.observers.remove(obs) # 自动通知全部观察者,推送最新信息 def notify(self): for obs in self.observers: obs.update(self) # 具体的发布者-公司公告中心HR class StaffNotice(Notice): def __init__(self, company_info=None): super().__init__() # 调用父类构造函数 self.__company_info = company_info # 公司信息,默认为 None @property def company_info(self): return self.__company_info # 获取公司信息 @company_info.setter def company_info(self, info): self.__company_info = info # 设置公司信息 self.notify() # 设置公司信息后,自动推送通知给所有观察者 # 具体的订阅者-公司员工 class Staff(Observer): def __init__(self): self.company_info = None # 初始化时员工对公司信息的了解为 None def update(self, notice): self.company_info = notice.company_info # 更新员工对公司信息的了解 # 客户端代码使用 notice = StaffNotice("初始公司信息") # 创建一个公司公告中心,初始信息为 "初始公司信息" s1 = Staff() # 创建 1 号员工 s2 = Staff() # 创建 2 号员工 notice.attach(s1) # 将 1 号员工添加到公告中心的观察者列表 notice.attach(s2) # 将 2 号员工添加到公告中心的观察者列表 notice.company_info = '公司发布了一个消息通知:明天工作' # 更新公司信息,触发通知 print(s1.company_info) # 输出:公司发布了一个消息通知:明天工作 print(s2.company_info) # 输出:公司发布了一个消息通知:明天工作 notice.detach(s2) # 2 号员工取消订阅 notice.company_info = '公司发布了一个消息通知:明天休息' # 再次更新公司信息,触发通知 print(s1.company_info) # 输出:公司发布了一个消息通知:明天休息 print(s2.company_info) # 输出:公司发布了一个消息通知:明天工作 (因为 s2 已经取消订阅) ``` ### 8、状态模式 ### 9、策略模式 #### 内容 > 定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。 #### 优点: - 定义了一些列可重用的算法和行为 - 消除了一些条件语句 - 可以提供相同行为的不同实现 #### 缺点: - 客户必须了解不同的策略 ```python # encoding: utf-8 # 项目名称: 常用设计模式 # @File : 015-策略模式.py # @Author: SunHao # @Desc : # @Date : 19:22 2024/11/06 from abc import ABC, abstractmethod # 定义策略接口,所有具体策略都必须实现这个接口 class Strategy(ABC): @abstractmethod def execute(self, data): pass # 具体策略需要实现的方法,用于执行具体的策略逻辑 # 快速策略类,实现了策略接口 class FastStrategy(Strategy): def execute(self, data): print(f'使用较快的策略处理 {data}') # 执行快速策略的具体逻辑 # 慢速策略类,也实现了策略接口 class SlowStrategy(Strategy): def execute(self, data): print(f'使用较慢的策略处理 {data}') # 执行慢速策略的具体逻辑 # 上下文类,用于在运行时选择具体的策略 class Context: def __init__(self, strategy, data): self._strategy = strategy # 初始化时设置默认策略 self._data = data # 需要处理的数据 def set_strategy(self, strategy): self._strategy = strategy # 运行时可以更换策略 def do_strategy(self): self._strategy.execute(self._data) # 调用当前策略的执行方法 # 客户端代码示例 data = {"ak": "12346789", "sk": "abcdefg"} # 示例数据 # 创建一个使用快速策略的上下文对象 ctx1 = Context(FastStrategy(), data) ctx1.do_strategy() # 执行快速策略 # 更改为慢速策略并执行 ctx1.set_strategy(SlowStrategy()) ctx1.do_strategy() # 执行慢速策略 ``` ### 10、访问者模式 ### 11、模板方法模式 #### 内容: > 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。 > 模板使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤 #### 使用场景: - 一次性实现一个算法中不变的那部分 - 各个子类中的公共行为应该被提取出来并集中到一个公共分类中以避免重复代码 - 控制子类的扩展 ```python # encoding: utf-8 # 项目名称: 常用设计模式 # @File : 016-模板方法.py # @Author: SunHao # @Desc : # @Date : 19:54 2024/11/06 from abc import ABCMeta, abstractmethod from time import sleep # 定义一个抽象基类 Window,使用 ABCMeta 元类来定义抽象方法 class Window(metaclass=ABCMeta): @abstractmethod def start(self): pass # 抽象方法,子类必须实现,用于启动窗口 @abstractmethod def repaint(self): pass # 抽象方法,子类必须实现,用于重新绘制窗口内容 @abstractmethod def stop(self): # 钩子操作 pass # 抽象方法,子类必须实现,用于停止窗口 def run(self): # 模板方法,定义了算法骨架 self.start() # 启动窗口 while True: try: self.repaint() # 重新绘制窗口内容 sleep(1) # 每隔一秒重新绘制一次 except KeyboardInterrupt: # 捕获键盘中断信号(Ctrl+C),退出循环 break self.stop() # 停止窗口 # 具体窗口类 MyWindow,继承自 Window 抽象基类 class MyWindow(Window): def __init__(self, msg): self.msg = msg # 初始化窗口消息 def start(self): print('窗口开始运行') # 实现启动窗口的具体逻辑 def stop(self): print('窗口结束运行') # 实现停止窗口的具体逻辑 def repaint(self): print(self.msg) # 实现重新绘制窗口的具体逻辑 # 客户端代码 MyWindow('Hello World').run() # 创建 MyWindow 对象并运行 ```