百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

30天学会Python编程:24. Python设计模式与架构

wptr33 2025-07-08 23:41 12 浏览

24.1 设计模式基础

24.1.1 设计模式分类

24.1.2 SOLID原则

原则

全称

核心思想

SRP

单一职责

一个类只做一件事

OCP

开闭原则

对扩展开放,修改关闭

LSP

里氏替换

子类可替换父类

ISP

接口隔离

客户端不应依赖不需要的接口

DIP

依赖倒置

依赖抽象而非实现

24.2 创建型模式

24.2.1 工厂模式

from abc import ABC, abstractmethod

class PaymentMethod(ABC):
    """支付方式抽象类"""
    @abstractmethod
    def pay(self, amount):
        pass

class CreditCard(PaymentMethod):
    def pay(self, amount):
        print(f"信用卡支付 {amount} 元")

class Alipay(PaymentMethod):
    def pay(self, amount):
        print(f"支付宝支付 {amount} 元")

class PaymentFactory:
    """支付工厂"""
    @staticmethod
    def create(method: str) -> PaymentMethod:
        if method == 'credit':
            return CreditCard()
        elif method == 'alipay':
            return Alipay()
        raise ValueError(f"不支持的支付方式: {method}")

# 使用示例
payment = PaymentFactory.create('alipay')
payment.pay(100)

24.2.2 单例模式

class DatabaseConnection:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            # 初始化数据库连接
            cls._instance.conn = "模拟数据库连接"
        return cls._instance
    
    def query(self, sql):
        print(f"执行查询: {sql}")
        return "结果数据"

# 测试单例
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2)  # True

24.3 结构型模式

24.3.1 适配器模式

class OldSystem:
    """旧系统接口"""
    def legacy_request(self, data: dict):
        print(f"旧系统处理: {data}")

class NewSystem:
    """新系统期望的接口"""
    def json_request(self, json_str: str):
        print(f"新系统处理: {json_str}")

class Adapter(NewSystem):
    """适配器转换旧系统接口"""
    def __init__(self, old_system: OldSystem):
        self.old_system = old_system
    
    def json_request(self, json_str: str):
        import json
        data = json.loads(json_str)
        self.old_system.legacy_request(data)

# 客户端代码
def client_code(system: NewSystem):
    system.json_request('{"key": "value"}')

old = OldSystem()
adapter = Adapter(old)
client_code(adapter)  # 通过适配器调用旧系统

24.3.2 装饰器模式

from functools import wraps

def log_execution(func):
    """记录函数执行的装饰器"""
    @wraps(func)
    def wrapper(*args, **kwargs):
        print(f"开始执行 {func.__name__}")
        result = func(*args, **kwargs)
        print(f"完成执行 {func.__name__}")
        return result
    return wrapper

def validate_input(func):
    """验证参数的装饰器"""
    @wraps(func)
    def wrapper(text: str):
        if not isinstance(text, str):
            raise ValueError("输入必须是字符串")
        return func(text)
    return wrapper

@log_execution
@validate_input
def process_text(text):
    """处理文本"""
    return text.upper()

# 使用装饰后的函数
print(process_text("hello"))  # 正常执行
# process_text(123)          # 触发验证错误

24.4 行为型模式

24.4.1 观察者模式

class Subject:
    """被观察者"""
    def __init__(self):
        self._observers = []
    
    def attach(self, observer):
        self._observers.append(observer)
    
    def detach(self, observer):
        self._observers.remove(observer)
    
    def notify(self, data):
        for observer in self._observers:
            observer.update(data)

class Observer(ABC):
    """观察者抽象类"""
    @abstractmethod
    def update(self, data):
        pass

class Logger(Observer):
    """日志观察者"""
    def update(self, data):
        print(f"[LOG] 状态变化: {data}")

class AlertSystem(Observer):
    """告警观察者"""
    def update(self, data):
        if data.get('warning'):
            print(f"[ALERT] 警告: {data['warning']}")

# 使用示例
subject = Subject()
subject.attach(Logger())
subject.attach(AlertSystem())

subject.notify({"status": "OK"})
subject.notify({"warning": "CPU过载"})

24.4.2 策略模式

from abc import ABC, abstractmethod

class CompressionStrategy(ABC):
    """压缩策略接口"""
    @abstractmethod
    def compress(self, data: bytes) -> bytes:
        pass

class ZipCompression(CompressionStrategy):
    def compress(self, data):
        print("使用ZIP算法压缩")
        return b"compressed_with_zip"

class RarCompression(CompressionStrategy):
    def compress(self, data):
        print("使用RAR算法压缩")
        return b"compressed_with_rar"

class FileCompressor:
    """文件压缩器"""
    def __init__(self, strategy: CompressionStrategy):
        self._strategy = strategy
    
    def set_strategy(self, strategy: CompressionStrategy):
        self._strategy = strategy
    
    def compress_file(self, file_path: str) -> bytes:
        with open(file_path, 'rb') as f:
            data = f.read()
        return self._strategy.compress(data)

# 使用示例
compressor = FileCompressor(ZipCompression())
compressor.compress_file("test.txt")

# 运行时切换策略
compressor.set_strategy(RarCompression())
compressor.compress_file("test.txt")

24.5 系统架构

24.5.1 分层架构

myapp/
├── presentation/   # 表现层
│   ├── web/
│   └── cli/
├── service/        # 业务逻辑层
│   ├── order.py
│   └── payment.py
├── repository/     # 数据访问层
│   ├── models.py
│   └── db.py
└── domain/         # 领域模型
    ├── entities.py
    └── value_objects.py

24.5.2 微服务通信

# 基于消息队列的通信
import pika

def publish_event(event):
    connection = pika.BlockingConnection(
        pika.ConnectionParameters('localhost')
    )
    channel = connection.channel()
    channel.queue_declare(queue='order_events')
    channel.basic_publish(
        exchange='',
        routing_key='order_events',
        body=json.dumps(event)
    )
    connection.close()

# 基于REST的通信
import requests

def get_user_info(user_id):
    response = requests.get(
        f"http://user-service/api/users/{user_id}",
        timeout=3
    )
    response.raise_for_status()
    return response.json()

24.6 应用举例

案例1:电商订单

from dataclasses import dataclass
from typing import List

@dataclass
class OrderItem:
    product_id: str
    quantity: int
    price: float

class Order:
    """订单领域模型"""
    def __init__(self, order_id: str, user_id: str):
        self.order_id = order_id
        self.user_id = user_id
        self._items: List[OrderItem] = []
        self._status = "created"
    
    def add_item(self, item: OrderItem):
        self._items.append(item)
    
    @property
    def total_amount(self):
        return sum(item.price * item.quantity for item in self._items)
    
    def checkout(self, payment_strategy):
        """策略模式应用"""
        payment_strategy.process(self.total_amount)
        self._status = "paid"
    
    def notify_observers(self, event):
        """观察者模式应用"""
        for observer in self._observers:
            observer.update(event)

class OrderService:
    """订单服务层"""
    def __init__(self, repository, notifier):
        self._repo = repository
        self._notifier = notifier
    
    def create_order(self, user_id, items):
        order = Order(str(uuid.uuid4()), user_id)
        for item in items:
            order.add_item(OrderItem(**item))
        
        self._repo.save(order)
        self._notifier.send(
            "order_created",
            {"order_id": order.order_id, "user_id": user_id}
        )
        return order

案例2:数据管道架构

from abc import ABC, abstractmethod
from concurrent.futures import ThreadPoolExecutor

class DataSource(ABC):
    """数据源抽象类"""
    @abstractmethod
    def read(self):
        pass

class Transformer(ABC):
    """数据转换抽象类"""
    @abstractmethod
    def transform(self, data):
        pass

class DataPipeline:
    """数据处理管道"""
    def __init__(self, source: DataSource, transformers: List[Transformer]):
        self.source = source
        self.transformers = transformers
        self.executor = ThreadPoolExecutor(max_workers=4)
    
    def process(self):
        """责任链模式处理数据"""
        raw_data = self.source.read()
        
        result = raw_data
        for transformer in self.transformers:
            result = self.executor.submit(transformer.transform, result).result()
        
        return result

# 具体实现
class CSVSource(DataSource):
    def read(self):
        print("从CSV读取数据")
        return [{"name": "Alice", "age": "25"}, {"name": "Bob", "age": "30"}]

class AgeToInt(Transformer):
    def transform(self, data):
        print("转换年龄为整数")
        for item in data:
            item['age'] = int(item['age'])
        return data

class AddTimestamp(Transformer):
    def transform(self, data):
        print("添加时间戳")
        for item in data:
            item['timestamp'] = datetime.now().isoformat()
        return data

# 构建管道
pipeline = DataPipeline(
    source=CSVSource(),
    transformers=[AgeToInt(), AddTimestamp()]
)
processed_data = pipeline.process()
print(processed_data)

24.7 知识图谱

24.8 学习总结

核心要点

  • 理解SOLID设计原则
  • 掌握常用设计模式
  • 区分架构层次职责
  • 合理应用模式组合

持续更新Python编程学习日志与技巧,敬请关注!


#编程# #学习# #python# #在头条记录我的2025#


相关推荐

SQL轻松入门(5):窗口函数(sql语录中加窗口函数的执行)

01前言标题中有2个字让我在初次接触窗口函数时,真真切切明白了何谓”高级”?说来也是一番辛酸史!话说,我见识了窗口函数的强大后,便磨拳擦掌的要试验一番,结果在查询中输入语句,返回的结果却是报错,Wh...

28个SQL常用的DeepSeek提示词指令,码住直接套用

自从DeepSeek出现后,极大地提升了大家平时的工作效率,特别是对于一些想从事数据行业的小白,只需要掌握DeepSeek的提问技巧,SQL相关的问题也不再是个门槛。...

从零开始学SQL进阶,数据分析师必备SQL取数技巧,建议收藏

上一节给大家讲到SQL取数的一些基本内容,包含SQL简单查询与高级查询,需要复习相关知识的同学可以跳转至上一节,本节给大家讲解SQL的进阶应用,在实际过程中用途比较多的子查询与窗口函数,下面一起学习。...

SQL_OVER语法(sql语句over什么含义)

OVER的定义OVER用于为行定义一个窗口,它对一组值进行操作,不需要使用GROUPBY子句对数据进行分组,能够在同一行中同时返回基础行的列和聚合列。...

SQL窗口函数知多少?(sql窗口怎么执行)

我们在日常工作中是否经常会遇到需要排名的情况,比如:每个部门按业绩来排名,每人按绩效排名,对部门销售业绩前N名的进行奖励等。面对这类需求,我们就需要使用sql的高级功能——窗口函数。...

如何学习并掌握 SQL 数据库基础:从零散查表到高效数据提取

无论是职场数据分析、产品运营,还是做副业项目,掌握SQL(StructuredQueryLanguage)意味着你能直接从数据库中提取、分析、整合数据,而不再依赖他人拉数,节省大量沟通成本,让你...

SQL窗口函数(sql窗口函数执行顺序)

背景在数据分析中,经常会遇到按某某条件来排名、并找出排名的前几名,用日常SQL的GROUPBY,ORDERBY来实现特别的麻烦,有时甚至实现不了,这个时候SQL窗口函数就能发挥巨大作用了,窗...

sqlserver删除重复数据只保留一条,使用ROW_NUMER()与Partition By

1.使用场景:公司的小程序需要实现一个功能:在原有小程序上,有一个优惠券活动表。存储着活动产品数据,但因为之前没有做约束,导致数据的不唯一,这会使打开产品详情页时,可能会出现随机显示任意活动问题。...

SQL面试经典问题(一)(sql经典面试题及答案)

以下是三个精心挑选的经典SQL面试问题及其详细解决方案,涵盖了数据分析、排序限制和数据清理等常见场景。这些问题旨在考察SQL的核心技能,适用于初学者到高级开发者的面试准备。每个问题均包含清晰的...

SQL:求连续N天的登陆人员之通用解答

前几天发了一个微头条:...

SQL四大排序函数神技(sql中的排序是什么语句)

在日常SQL开发中,排序操作无处不在。当大家需要排序时,是否只会想到ORDERBY?今天,我们就来揭秘SQL中四个强大却常被忽略的排序函数:ROW_NUMBER()、RANK()、DENSE_RAN...

四、mysql窗口函数之row_number()函数的使用

1、窗口函数之row_number()使用背景窗口函数中,排序函数rank(),dense_rank()虽说都是排序函数,但是各有用处,假如像上章节说的“同组同分”两条数据,我们不想“班级名次”出现“...

ROW_NUMBER()函数(rownumber函数与rank区别)

ROW_NUMBER()是SQL中的一个窗口函数(WindowFunction)...

Dify「模板转换」节点终极指南:动态文本生成进阶技巧(附代码)Jinja2引擎解析

这篇文章是关于Dify「模板转换」节点的终极指南,解析了基于Jinja2模板引擎的动态文本生成技巧,涵盖多源文本整合、知识检索结构化、动态API构建及个性化内容生成等六大应用场景,助力开发者高效利用模...

Python 最常用的语句、函数有哪些?

1.#coding=utf-8①代码中有中文字符,最好在代码前面加#coding=utf-8②pycharm不加可能不会报错,但是代码最终是会放到服务器上,放到服务器上的时候运行可能会报错。③...