目录
- Python设计模式实战:用Pythonic的方式实现单例、工厂模式
-
- [1. 引言](#1. 引言)
- [2. Pythonic编程哲学](#2. Pythonic编程哲学)
-
- [2.1 Python之禅(The Zen of Python)](#2.1 Python之禅(The Zen of Python))
- [2.2 Pythonic代码的特征](#2.2 Pythonic代码的特征)
- [3. 单例模式(Singleton Pattern)](#3. 单例模式(Singleton Pattern))
-
- [3.1 单例模式概述](#3.1 单例模式概述)
- [3.2 模块级别的单例](#3.2 模块级别的单例)
- [3.3 使用元类实现单例](#3.3 使用元类实现单例)
- [3.4 使用装饰器实现单例](#3.4 使用装饰器实现单例)
- [3.5 单例模式的最佳实践](#3.5 单例模式的最佳实践)
- [4. 工厂模式(Factory Pattern)](#4. 工厂模式(Factory Pattern))
-
- [4.1 工厂模式概述](#4.1 工厂模式概述)
- [4.2 简单工厂模式](#4.2 简单工厂模式)
- [4.3 工厂方法模式](#4.3 工厂方法模式)
- [4.4 抽象工厂模式](#4.4 抽象工厂模式)
- [5. 完整代码示例](#5. 完整代码示例)
- [6. 设计模式的最佳实践](#6. 设计模式的最佳实践)
-
- [6.1 Pythonic设计原则](#6.1 Pythonic设计原则)
- [6.2 测试策略](#6.2 测试策略)
- [7. 性能考虑与优化](#7. 性能考虑与优化)
-
- [7.1 单例模式的性能优化](#7.1 单例模式的性能优化)
- [7.2 工厂模式的性能优化](#7.2 工厂模式的性能优化)
- [8. 总结](#8. 总结)
-
- [8.1 单例模式要点](#8.1 单例模式要点)
- [8.2 工厂模式要点](#8.2 工厂模式要点)
- [8.3 Pythonic设计原则](#8.3 Pythonic设计原则)
- [8.4 实际应用建议](#8.4 实际应用建议)
『宝藏代码胶囊开张啦!』------ 我的 CodeCapsule 来咯!✨
写代码不再头疼!我的新站点 CodeCapsule 主打一个 "白菜价"+"量身定制 "!无论是卡脖子的毕设/课设/文献复现 ,需要灵光一现的算法改进 ,还是想给项目加个"外挂",这里都有便宜又好用的代码方案等你发现!低成本,高适配,助你轻松通关!速来围观 👉 CodeCapsule官网
Python设计模式实战:用Pythonic的方式实现单例、工厂模式
1. 引言
设计模式是软件工程中解决常见问题的经典方案,它们代表了最佳的实践经验。然而,在Python这样具有独特哲学的语言中,传统的设计模式实现方式往往显得过于复杂和"不Pythonic"。Pythonic的代码应该简洁、可读性强,并且充分利用Python的语言特性。
本文将深入探讨如何在Python中优雅地实现单例模式和工厂模式,展示Python特有的实现方式,并提供实际的应用场景示例。我们将避免Java或C++风格的冗长实现,转而采用符合Python哲学的精炼代码。
2. Pythonic编程哲学
2.1 Python之禅(The Zen of Python)
在深入设计模式之前,让我们回顾一下Python的核心哲学:
python
import this
输出结果体现了Python的设计原则:
- 优美胜于丑陋
- 明了胜于晦涩
- 简单胜于复杂
- 扁平胜于嵌套
- 可读性很重要
2.2 Pythonic代码的特征
Pythonic代码具有以下特点:
- 充分利用Python的内置特性
- 代码简洁但功能强大
- 遵循约定俗成的惯例
- 易于阅读和维护
- 避免不必要的复杂性
3. 单例模式(Singleton Pattern)
3.1 单例模式概述
单例模式确保一个类只有一个实例,并提供一个全局访问点。在Python中,我们有多种方式实现单例,每种方式都有其适用场景。
3.2 模块级别的单例
在Python中,模块本身就是天然的单例,这是最简单也是最Pythonic的实现方式:
python
# singleton_module.py
"""
模块级别的单例实现
这是最Pythonic的单例实现方式
"""
class _DatabaseConnection:
"""数据库连接类,通过模块实现单例"""
def __init__(self):
self.connection_count = 0
self.is_connected = False
def connect(self):
"""模拟数据库连接"""
if not self.is_connected:
self.connection_count += 1
self.is_connected = True
print(f"数据库连接已建立 (连接次数: {self.connection_count})")
else:
print("数据库已经连接")
def disconnect(self):
"""模拟断开数据库连接"""
if self.is_connected:
self.is_connected = False
print("数据库连接已断开")
else:
print("数据库未连接")
def execute_query(self, query):
"""执行查询"""
if self.is_connected:
print(f"执行查询: {query}")
return f"查询结果: {query}"
else:
raise ConnectionError("数据库未连接")
# 创建单例实例
database = _DatabaseConnection()
# 使用示例
if __name__ == "__main__":
# 在另一个模块中,只需要导入database即可使用单例
from singleton_module import database
database.connect()
database.execute_query("SELECT * FROM users")
database.disconnect()
3.3 使用元类实现单例
元类提供了更灵活的单例控制方式:
python
class SingletonMeta(type):
"""
单例元类
使用元类控制类的创建过程,确保只有一个实例
"""
_instances = {}
def __call__(cls, *args, **kwargs):
"""
当类被调用(实例化)时触发
"""
if cls not in cls._instances:
instance = super().__call__(*args, **kwargs)
cls._instances[cls] = instance
return cls._instances[cls]
class ConfigurationManager(metaclass=SingletonMeta):
"""
配置管理器单例
使用元类实现单例模式
"""
def __init__(self):
self._config = {}
self._load_default_config()
def _load_default_config(self):
"""加载默认配置"""
self._config = {
'app_name': 'My Application',
'version': '1.0.0',
'debug': False,
'database_url': 'sqlite:///default.db',
'max_connections': 10
}
def get(self, key, default=None):
"""获取配置值"""
return self._config.get(key, default)
def set(self, key, value):
"""设置配置值"""
self._config[key] = value
def update(self, **kwargs):
"""批量更新配置"""
self._config.update(kwargs)
def __getitem__(self, key):
"""支持下标访问"""
return self._config[key]
def __setitem__(self, key, value):
"""支持下标设置"""
self._config[key] = value
def __contains__(self, key):
"""支持in操作符"""
return key in self._config
def __str__(self):
"""字符串表示"""
return f"ConfigurationManager(config={self._config})"
# 使用示例
def test_configuration_singleton():
"""测试配置管理器单例"""
config1 = ConfigurationManager()
config2 = ConfigurationManager()
print(f"config1 is config2: {config1 is config2}") # 输出: True
# 设置配置
config1.set('debug', True)
config1['timeout'] = 30
# 在另一个实例中访问
print(f"config2 debug mode: {config2.get('debug')}") # 输出: True
print(f"config2 timeout: {config2['timeout']}") # 输出: 30
# 测试包含检查
print(f"'version' in config1: {'version' in config1}") # 输出: True
3.4 使用装饰器实现单例
装饰器提供了另一种优雅的单例实现方式:
python
from functools import wraps
from threading import Lock
def singleton(cls):
"""
单例装饰器
使用装饰器实现线程安全的单例模式
"""
instances = {}
lock = Lock()
@wraps(cls)
def get_instance(*args, **kwargs):
with lock:
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
def singleton_with_parameters(*singleton_args, **singleton_kwargs):
"""
带参数的单例装饰器
支持根据不同的参数创建不同的单例实例
"""
def decorator(cls):
instances = {}
lock = Lock()
@wraps(cls)
def get_instance(*args, **kwargs):
# 根据装饰器参数和实例化参数生成唯一键
key = (singleton_args, tuple(sorted(singleton_kwargs.items())),
args, tuple(sorted(kwargs.items())))
with lock:
if key not in instances:
instances[key] = cls(*args, **kwargs)
return instances[key]
return get_instance
return decorator
@singleton
class Logger:
"""
日志管理器单例
使用装饰器实现单例模式
"""
def __init__(self):
self._logs = []
self._log_level = 'INFO'
def set_level(self, level):
"""设置日志级别"""
self._log_level = level.upper()
def log(self, message, level='INFO'):
"""记录日志"""
timestamp = self._get_timestamp()
log_entry = {
'timestamp': timestamp,
'level': level.upper(),
'message': message
}
self._logs.append(log_entry)
if self._should_log(level):
print(f"[{level.upper()}] {timestamp}: {message}")
def _get_timestamp(self):
"""获取时间戳"""
from datetime import datetime
return datetime.now().isoformat()
def _should_log(self, level):
"""判断是否应该记录日志"""
levels = {'DEBUG': 0, 'INFO': 1, 'WARNING': 2, 'ERROR': 3, 'CRITICAL': 4}
current_level = levels.get(self._log_level, 1)
message_level = levels.get(level.upper(), 1)
return message_level >= current_level
def get_logs(self, level=None):
"""获取日志记录"""
if level:
return [log for log in self._logs if log['level'] == level.upper()]
return self._logs.copy()
def clear_logs(self):
"""清空日志"""
self._logs.clear()
@singleton_with_parameters(scope='application')
class CacheManager:
"""
缓存管理器
使用带参数的装饰器实现单例
"""
def __init__(self, name="default"):
self.name = name
self._cache = {}
self._hits = 0
self._misses = 0
def set(self, key, value, ttl=None):
"""设置缓存值"""
import time
expire_time = time.time() + ttl if ttl else None
self._cache[key] = {
'value': value,
'expire_time': expire_time
}
def get(self, key):
"""获取缓存值"""
import time
if key in self._cache:
item = self._cache[key]
if item['expire_time'] is None or item['expire_time'] > time.time():
self._hits += 1
return item['value']
else:
# 过期删除
del self._cache[key]
self._misses += 1
return None
def delete(self, key):
"""删除缓存值"""
if key in self._cache:
del self._cache[key]
return True
return False
def clear(self):
"""清空缓存"""
self._cache.clear()
self._hits = 0
self._misses = 0
def stats(self):
"""获取缓存统计"""
hit_rate = self._hits / (self._hits + self._misses) if (self._hits + self._misses) > 0 else 0
return {
'hits': self._hits,
'misses': self._misses,
'hit_rate': hit_rate,
'size': len(self._cache)
}
3.5 单例模式的最佳实践
python
class PythonicSingleton:
"""
Pythonic单例模式最佳实践
结合了多种Python特性的单例实现
"""
_instance = None
_initialized = False
def __new__(cls, *args, **kwargs):
"""
控制实例创建
"""
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
"""
确保只初始化一次
"""
if not self._initialized:
self._initialize()
self._initialized = True
def _initialize(self):
"""初始化方法"""
self.data = {}
self.initialization_time = self._get_current_time()
def _get_current_time(self):
"""获取当前时间"""
from datetime import datetime
return datetime.now()
def __repr__(self):
return f"<PythonicSingleton at {id(self)}>"
@classmethod
def get_instance(cls):
"""获取单例实例的类方法"""
if cls._instance is None:
cls()
return cls._instance
4. 工厂模式(Factory Pattern)
4.1 工厂模式概述
工厂模式提供了一种创建对象的方式,而无需指定具体的类。在Python中,我们可以利用动态语言的特性实现更加灵活的工厂模式。
4.2 简单工厂模式
python
from enum import Enum
from typing import Dict, Type, Any
class NotificationType(Enum):
"""通知类型枚举"""
EMAIL = "email"
SMS = "sms"
PUSH = "push"
SLACK = "slack"
class Notification:
"""通知基类"""
def __init__(self, recipient: str, message: str):
self.recipient = recipient
self.message = message
def send(self) -> bool:
"""发送通知"""
raise NotImplementedError("子类必须实现send方法")
def validate(self) -> bool:
"""验证通知参数"""
return bool(self.recipient and self.message)
class EmailNotification(Notification):
"""邮件通知"""
def send(self) -> bool:
print(f"发送邮件给 {self.recipient}: {self.message}")
# 模拟发送逻辑
return True
def __str__(self):
return f"EmailNotification(to={self.recipient})"
class SMSNotification(Notification):
"""短信通知"""
def send(self) -> bool:
print(f"发送短信给 {self.recipient}: {self.message}")
# 模拟发送逻辑
return True
def __str__(self):
return f"SMSNotification(to={self.recipient})"
class PushNotification(Notification):
"""推送通知"""
def send(self) -> bool:
print(f"发送推送给 {self.recipient}: {self.message}")
# 模拟发送逻辑
return True
def __str__(self):
return f"PushNotification(to={self.recipient})"
class NotificationFactory:
"""
通知工厂类
简单工厂模式实现
"""
# 注册的通知类型映射
_notification_types: Dict[NotificationType, Type[Notification]] = {
NotificationType.EMAIL: EmailNotification,
NotificationType.SMS: SMSNotification,
NotificationType.PUSH: PushNotification,
}
@classmethod
def create_notification(cls,
notification_type: NotificationType,
recipient: str,
message: str,
**kwargs) -> Notification:
"""
创建通知实例
Args:
notification_type: 通知类型
recipient: 接收者
message: 消息内容
**kwargs: 额外参数
Returns:
Notification实例
"""
if notification_type not in cls._notification_types:
raise ValueError(f"不支持的通知类型: {notification_type}")
notification_class = cls._notification_types[notification_type]
return notification_class(recipient, message, **kwargs)
@classmethod
def register_notification_type(cls,
notification_type: NotificationType,
notification_class: Type[Notification]):
"""
注册新的通知类型
Args:
notification_type: 通知类型
notification_class: 通知类
"""
if not issubclass(notification_class, Notification):
raise TypeError("通知类必须继承自Notification")
cls._notification_types[notification_type] = notification_class
print(f"已注册通知类型: {notification_type} -> {notification_class.__name__}")
@classmethod
def list_notification_types(cls) -> list:
"""列出所有支持的通知类型"""
return list(cls._notification_types.keys())
# 使用示例
def test_notification_factory():
"""测试通知工厂"""
# 创建不同类型的通知
email_notification = NotificationFactory.create_notification(
NotificationType.EMAIL,
"user@example.com",
"欢迎使用我们的服务!"
)
sms_notification = NotificationFactory.create_notification(
NotificationType.SMS,
"+1234567890",
"您的验证码是: 123456"
)
# 发送通知
notifications = [email_notification, sms_notification]
for notification in notifications:
if notification.validate():
success = notification.send()
print(f"{notification} 发送{'成功' if success else '失败'}")
4.3 工厂方法模式
python
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import List
@dataclass
class Document:
"""文档数据类"""
title: str
content: str
format: str
def display(self):
"""显示文档信息"""
print(f"文档: {self.title}")
print(f"格式: {self.format}")
print(f"内容: {self.content[:50]}..." if len(self.content) > 50 else f"内容: {self.content}")
class DocumentExporter(ABC):
"""
文档导出器抽象基类
工厂方法模式
"""
def __init__(self, document: Document):
self.document = document
@abstractmethod
def export(self) -> str:
"""导出文档"""
pass
def pre_process(self) -> None:
"""预处理文档"""
print(f"预处理文档: {self.document.title}")
def post_process(self, exported_content: str) -> str:
"""后处理导出内容"""
print(f"后处理导出内容")
return exported_content
def export_document(self) -> str:
"""导出文档的模板方法"""
self.pre_process()
content = self.export()
return self.post_process(content)
class PDFExporter(DocumentExporter):
"""PDF导出器"""
def export(self) -> str:
"""导出为PDF格式"""
print(f"将文档 '{self.document.title}' 导出为PDF")
return f"PDF内容: {self.document.content}"
class WordExporter(DocumentExporter):
"""Word文档导出器"""
def export(self) -> str:
"""导出为Word格式"""
print(f"将文档 '{self.document.title}' 导出为Word文档")
return f"Word内容: {self.document.content}"
class HTMLExporter(DocumentExporter):
"""HTML导出器"""
def export(self) -> str:
"""导出为HTML格式"""
print(f"将文档 '{self.document.title}' 导出为HTML")
html_content = f"""
<!DOCTYPE html>
<html>
<head>
<title>{self.document.title}</title>
</head>
<body>
<h1>{self.document.title}</h1>
<p>{self.document.content}</p>
</body>
</html>
"""
return html_content
class DocumentExportFactory:
"""
文档导出工厂
工厂方法模式实现
"""
_exporters = {
'pdf': PDFExporter,
'word': WordExporter,
'html': HTMLExporter
}
@classmethod
def create_exporter(cls, format_type: str, document: Document) -> DocumentExporter:
"""
创建文档导出器
Args:
format_type: 导出格式
document: 文档对象
Returns:
文档导出器实例
"""
if format_type not in cls._exporters:
raise ValueError(f"不支持的导出格式: {format_type}")
exporter_class = cls._exporters[format_type]
return exporter_class(document)
@classmethod
def register_exporter(cls, format_type: str, exporter_class: type):
"""注册新的导出器"""
if not issubclass(exporter_class, DocumentExporter):
raise TypeError("导出器必须继承自DocumentExporter")
cls._exporters[format_type] = exporter_class
print(f"已注册导出器: {format_type} -> {exporter_class.__name__}")
@classmethod
def get_supported_formats(cls) -> List[str]:
"""获取支持的导出格式"""
return list(cls._exporters.keys())
# 使用示例
def test_document_export():
"""测试文档导出"""
# 创建文档
document = Document(
title="Python设计模式指南",
content="本文介绍Python中的设计模式实现...",
format="markdown"
)
# 导出为不同格式
formats = ['pdf', 'word', 'html']
for format_type in formats:
print(f"\n--- 导出为 {format_type.upper()} ---")
try:
exporter = DocumentExportFactory.create_exporter(format_type, document)
result = exporter.export_document()
print(f"导出结果: {result[:100]}...")
except ValueError as e:
print(f"导出失败: {e}")
4.4 抽象工厂模式
python
from abc import ABC, abstractmethod
from enum import Enum
from typing import Protocol
class Theme(Enum):
"""主题枚举"""
LIGHT = "light"
DARK = "dark"
BLUE = "blue"
class Button(Protocol):
"""按钮接口"""
def render(self) -> str:
"""渲染按钮"""
...
def on_click(self) -> str:
"""点击事件"""
...
class Checkbox(Protocol):
"""复选框接口"""
def render(self) -> str:
"""渲染复选框"""
...
def toggle(self) -> str:
"""切换状态"""
...
class LightButton:
"""浅色主题按钮"""
def render(self) -> str:
return "渲染浅色按钮"
def on_click(self) -> str:
return "浅色按钮被点击"
class DarkButton:
"""深色主题按钮"""
def render(self) -> str:
return "渲染深色按钮"
def on_click(self) -> str:
return "深色按钮被点击"
class BlueButton:
"""蓝色主题按钮"""
def render(self) -> str:
return "渲染蓝色按钮"
def on_click(self) -> str:
return "蓝色按钮被点击"
class LightCheckbox:
"""浅色主题复选框"""
def __init__(self):
self.checked = False
def render(self) -> str:
state = "选中" if self.checked else "未选中"
return f"浅色复选框 [{state}]"
def toggle(self) -> str:
self.checked = not self.checked
state = "选中" if self.checked else "未选中"
return f"浅色复选框状态: {state}"
class DarkCheckbox:
"""深色主题复选框"""
def __init__(self):
self.checked = False
def render(self) -> str:
state = "选中" if self.checked else "未选中"
return f"深色复选框 [{state}]"
def toggle(self) -> str:
self.checked = not self.checked
state = "选中" if self.checked else "未选中"
return f"深色复选框状态: {state}"
class BlueCheckbox:
"""蓝色主题复选框"""
def __init__(self):
self.checked = False
def render(self) -> str:
state = "选中" if self.checked else "未选中"
return f"蓝色复选框 [{state}]"
def toggle(self) -> str:
self.checked = not self.checked
state = "选中" if self.checked else "未选中"
return f"蓝色复选框状态: {state}"
class GUIFactory(ABC):
"""
GUI工厂抽象基类
抽象工厂模式
"""
@abstractmethod
def create_button(self) -> Button:
"""创建按钮"""
pass
@abstractmethod
def create_checkbox(self) -> Checkbox:
"""创建复选框"""
pass
class LightThemeFactory(GUIFactory):
"""浅色主题工厂"""
def create_button(self) -> Button:
return LightButton()
def create_checkbox(self) -> Checkbox:
return LightCheckbox()
class DarkThemeFactory(GUIFactory):
"""深色主题工厂"""
def create_button(self) -> Button:
return DarkButton()
def create_checkbox(self) -> Checkbox:
return DarkCheckbox()
class BlueThemeFactory(GUIFactory):
"""蓝色主题工厂"""
def create_button(self) -> Button:
return BlueButton()
def create_checkbox(self) -> Checkbox:
return BlueCheckbox()
class ThemeFactory:
"""
主题工厂
抽象工厂的工厂
"""
_factories = {
Theme.LIGHT: LightThemeFactory,
Theme.DARK: DarkThemeFactory,
Theme.BLUE: BlueThemeFactory
}
@classmethod
def create_factory(cls, theme: Theme) -> GUIFactory:
"""
创建主题工厂
Args:
theme: 主题类型
Returns:
GUI工厂实例
"""
if theme not in cls._factories:
raise ValueError(f"不支持的主题: {theme}")
factory_class = cls._factories[theme]
return factory_class()
@classmethod
def register_theme(cls, theme: Theme, factory_class: type):
"""注册新主题"""
if not issubclass(factory_class, GUIFactory):
raise TypeError("工厂类必须继承自GUIFactory")
cls._factories[theme] = factory_class
print(f"已注册主题: {theme} -> {factory_class.__name__}")
class Application:
"""
应用程序类
使用抽象工厂创建UI组件
"""
def __init__(self, theme: Theme):
self.theme = theme
self.factory = ThemeFactory.create_factory(theme)
self.button = None
self.checkbox = None
def create_ui(self):
"""创建用户界面"""
self.button = self.factory.create_button()
self.checkbox = self.factory.create_checkbox()
print(f"使用 {self.theme.value} 主题创建UI")
print(f"按钮: {self.button.render()}")
print(f"复选框: {self.checkbox.render()}")
def simulate_interaction(self):
"""模拟用户交互"""
if self.button and self.checkbox:
print(f"\n用户交互:")
print(self.button.on_click())
print(self.checkbox.toggle())
print(self.checkbox.toggle())
# 使用示例
def test_abstract_factory():
"""测试抽象工厂"""
themes = [Theme.LIGHT, Theme.DARK, Theme.BLUE]
for theme in themes:
print(f"\n{'='*50}")
print(f"测试 {theme.value.upper()} 主题")
print('='*50)
app = Application(theme)
app.create_ui()
app.simulate_interaction()
5. 完整代码示例
下面是一个完整的示例,展示了如何在真实场景中结合使用单例模式和工厂模式:
python
#!/usr/bin/env python3
"""
Python设计模式实战完整示例
结合单例模式和工厂模式的完整应用
"""
import json
import sqlite3
from abc import ABC, abstractmethod
from dataclasses import dataclass, asdict
from datetime import datetime
from enum import Enum
from typing import Dict, List, Optional, Any
from pathlib import Path
import logging
# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class StorageType(Enum):
"""存储类型枚举"""
MEMORY = "memory"
SQLITE = "sqlite"
JSON_FILE = "json_file"
@dataclass
class User:
"""用户数据类"""
id: int
name: str
email: str
created_at: str
updated_at: str
class UserRepository(ABC):
"""用户仓库抽象基类"""
@abstractmethod
def save(self, user: User) -> bool:
"""保存用户"""
pass
@abstractmethod
def find_by_id(self, user_id: int) -> Optional[User]:
"""根据ID查找用户"""
pass
@abstractmethod
def find_all(self) -> List[User]:
"""查找所有用户"""
pass
@abstractmethod
def delete(self, user_id: int) -> bool:
"""删除用户"""
pass
class MemoryUserRepository(UserRepository):
"""内存用户仓库"""
def __init__(self):
self._users: Dict[int, User] = {}
self._next_id = 1
def save(self, user: User) -> bool:
if user.id == 0: # 新用户
user.id = self._next_id
self._next_id += 1
user.updated_at = datetime.now().isoformat()
self._users[user.id] = user
logger.info(f"用户已保存到内存: {user}")
return True
def find_by_id(self, user_id: int) -> Optional[User]:
return self._users.get(user_id)
def find_all(self) -> List[User]:
return list(self._users.values())
def delete(self, user_id: int) -> bool:
if user_id in self._users:
del self._users[user_id]
logger.info(f"用户已从内存删除: {user_id}")
return True
return False
class SQLiteUserRepository(UserRepository):
"""SQLite用户仓库"""
def __init__(self, db_path: str = "users.db"):
self.db_path = db_path
self._init_database()
def _init_database(self):
"""初始化数据库"""
with sqlite3.connect(self.db_path) as conn:
conn.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
)
''')
conn.commit()
def save(self, user: User) -> bool:
with sqlite3.connect(self.db_path) as conn:
cursor = conn.cursor()
if user.id == 0: # 新用户
user.created_at = datetime.now().isoformat()
user.updated_at = user.created_at
cursor.execute('''
INSERT INTO users (name, email, created_at, updated_at)
VALUES (?, ?, ?, ?)
''', (user.name, user.email, user.created_at, user.updated_at))
user.id = cursor.lastrowid
else: # 更新用户
user.updated_at = datetime.now().isoformat()
cursor.execute('''
UPDATE users
SET name = ?, email = ?, updated_at = ?
WHERE id = ?
''', (user.name, user.email, user.updated_at, user.id))
conn.commit()
logger.info(f"用户已保存到SQLite: {user}")
return True
def find_by_id(self, user_id: int) -> Optional[User]:
with sqlite3.connect(self.db_path) as conn:
cursor = conn.cursor()
cursor.execute('SELECT * FROM users WHERE id = ?', (user_id,))
row = cursor.fetchone()
if row:
return User(*row)
return None
def find_all(self) -> List[User]:
with sqlite3.connect(self.db_path) as conn:
cursor = conn.cursor()
cursor.execute('SELECT * FROM users')
rows = cursor.fetchall()
return [User(*row) for row in rows]
def delete(self, user_id: int) -> bool:
with sqlite3.connect(self.db_path) as conn:
cursor = conn.cursor()
cursor.execute('DELETE FROM users WHERE id = ?', (user_id,))
conn.commit()
deleted = cursor.rowcount > 0
if deleted:
logger.info(f"用户已从SQLite删除: {user_id}")
return deleted
class JsonFileUserRepository(UserRepository):
"""JSON文件用户仓库"""
def __init__(self, file_path: str = "users.json"):
self.file_path = Path(file_path)
self._ensure_file_exists()
def _ensure_file_exists(self):
"""确保文件存在"""
if not self.file_path.exists():
self.file_path.write_text('[]')
def _read_users(self) -> List[User]:
"""读取用户数据"""
try:
data = json.loads(self.file_path.read_text())
return [User(**user_data) for user_data in data]
except (json.JSONDecodeError, KeyError):
return []
def _write_users(self, users: List[User]):
"""写入用户数据"""
data = [asdict(user) for user in users]
self.file_path.write_text(json.dumps(data, indent=2))
def save(self, user: User) -> bool:
users = self._read_users()
if user.id == 0: # 新用户
user.id = max([u.id for u in users], default=0) + 1
user.created_at = datetime.now().isoformat()
user.updated_at = user.created_at
users.append(user)
else: # 更新用户
for i, existing_user in enumerate(users):
if existing_user.id == user.id:
user.updated_at = datetime.now().isoformat()
users[i] = user
break
self._write_users(users)
logger.info(f"用户已保存到JSON文件: {user}")
return True
def find_by_id(self, user_id: int) -> Optional[User]:
users = self._read_users()
for user in users:
if user.id == user_id:
return user
return None
def find_all(self) -> List[User]:
return self._read_users()
def delete(self, user_id: int) -> bool:
users = self._read_users()
initial_count = len(users)
users = [user for user in users if user.id != user_id]
if len(users) < initial_count:
self._write_users(users)
logger.info(f"用户已从JSON文件删除: {user_id}")
return True
return False
class RepositoryFactory:
"""仓库工厂"""
_repositories = {
StorageType.MEMORY: MemoryUserRepository,
StorageType.SQLITE: SQLiteUserRepository,
StorageType.JSON_FILE: JsonFileUserRepository
}
@classmethod
def create_repository(cls, storage_type: StorageType, **kwargs) -> UserRepository:
"""创建用户仓库"""
if storage_type not in cls._repositories:
raise ValueError(f"不支持的存储类型: {storage_type}")
repository_class = cls._repositories[storage_type]
return repository_class(**kwargs)
@classmethod
def register_repository(cls, storage_type: StorageType, repository_class: type):
"""注册新的仓库类型"""
if not issubclass(repository_class, UserRepository):
raise TypeError("仓库类必须继承自UserRepository")
cls._repositories[storage_type] = repository_class
logger.info(f"已注册存储类型: {storage_type} -> {repository_class.__name__}")
class UserService:
"""
用户服务类
使用单例模式和工厂模式
"""
_instance = None
def __new__(cls, storage_type: StorageType = StorageType.MEMORY, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._initialized = False
return cls._instance
def __init__(self, storage_type: StorageType = StorageType.MEMORY, **kwargs):
if not self._initialized:
self.repository = RepositoryFactory.create_repository(storage_type, **kwargs)
self._initialized = True
logger.info(f"UserService已初始化,使用存储类型: {storage_type}")
def create_user(self, name: str, email: str) -> User:
"""创建用户"""
user = User(
id=0,
name=name,
email=email,
created_at="",
updated_at=""
)
if self.repository.save(user):
return user
else:
raise RuntimeError("创建用户失败")
def get_user(self, user_id: int) -> Optional[User]:
"""获取用户"""
return self.repository.find_by_id(user_id)
def get_all_users(self) -> List[User]:
"""获取所有用户"""
return self.repository.find_all()
def update_user(self, user_id: int, name: str = None, email: str = None) -> bool:
"""更新用户"""
user = self.repository.find_by_id(user_id)
if not user:
return False
if name:
user.name = name
if email:
user.email = email
return self.repository.save(user)
def delete_user(self, user_id: int) -> bool:
"""删除用户"""
return self.repository.delete(user_id)
@classmethod
def get_instance(cls) -> 'UserService':
"""获取单例实例"""
if cls._instance is None:
cls()
return cls._instance
def main():
"""主函数 - 演示完整的使用场景"""
print("=" * 60)
print("Python设计模式实战演示")
print("单例模式 + 工厂模式完整示例")
print("=" * 60)
# 测试不同的存储类型
storage_types = [
(StorageType.MEMORY, {}),
(StorageType.SQLITE, {"db_path": "test_users.db"}),
(StorageType.JSON_FILE, {"file_path": "test_users.json"})
]
for storage_type, kwargs in storage_types:
print(f"\n{'='*50}")
print(f"测试存储类型: {storage_type.value}")
print('='*50)
# 创建用户服务单例
user_service = UserService(storage_type, **kwargs)
# 测试单例特性
another_instance = UserService.get_instance()
print(f"单例验证: user_service is another_instance = {user_service is another_instance}")
# 创建用户
users_data = [
("张三", "zhangsan@example.com"),
("李四", "lisi@example.com"),
("王五", "wangwu@example.com")
]
created_users = []
for name, email in users_data:
user = user_service.create_user(name, email)
created_users.append(user)
print(f"创建用户: {user.name} (ID: {user.id})")
# 查询用户
print(f"\n所有用户:")
all_users = user_service.get_all_users()
for user in all_users:
print(f" - {user.id}: {user.name} <{user.email}>")
# 更新用户
if created_users:
first_user = created_users[0]
user_service.update_user(first_user.id, name="张三丰")
updated_user = user_service.get_user(first_user.id)
print(f"\n更新用户: {updated_user.name} <{updated_user.email}>")
# 删除用户
if len(created_users) > 1:
user_to_delete = created_users[1]
user_service.delete_user(user_to_delete.id)
print(f"\n删除用户: {user_to_delete.name}")
# 验证删除
remaining_users = user_service.get_all_users()
print(f"剩余用户数: {len(remaining_users)}")
print(f"\n{storage_type.value} 存储测试完成")
print("\n" + "=" * 60)
print("演示完成!")
print("=" * 60)
if __name__ == "__main__":
main()
6. 设计模式的最佳实践
6.1 Pythonic设计原则
- 简单优于复杂
python
# 不Pythonic
class ComplexSingleton:
_instance = None
_lock = threading.Lock()
def __new__(cls, *args, **kwargs):
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
# Pythonic
class SimpleSingleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
- 利用语言特性
python
# 使用模块作为单例
# database.py
class Database:
def connect(self):
pass
db = Database()
# 在其他模块中使用
from database import db
6.2 测试策略
python
import unittest
from unittest.mock import Mock, patch
class TestSingletonPattern(unittest.TestCase):
"""单例模式测试"""
def test_singleton_instance(self):
"""测试单例实例唯一性"""
instance1 = UserService.get_instance()
instance2 = UserService.get_instance()
self.assertIs(instance1, instance2)
self.assertEqual(id(instance1), id(instance2))
def test_singleton_initialization(self):
"""测试单例初始化"""
service = UserService.get_instance()
self.assertTrue(hasattr(service, 'repository'))
self.assertIsNotNone(service.repository)
class TestFactoryPattern(unittest.TestCase):
"""工厂模式测试"""
def test_repository_factory(self):
"""测试仓库工厂"""
# 测试内存仓库
memory_repo = RepositoryFactory.create_repository(StorageType.MEMORY)
self.assertIsInstance(memory_repo, MemoryUserRepository)
# 测试SQLite仓库
sqlite_repo = RepositoryFactory.create_repository(StorageType.SQLITE)
self.assertIsInstance(sqlite_repo, SQLiteUserRepository)
def test_factory_registration(self):
"""测试工厂注册机制"""
class TestRepository(UserRepository):
def save(self, user): return True
def find_by_id(self, user_id): return None
def find_all(self): return []
def delete(self, user_id): return True
# 注册新的仓库类型
RepositoryFactory.register_repository(StorageType.MEMORY, TestRepository)
# 验证注册成功
repo = RepositoryFactory.create_repository(StorageType.MEMORY)
self.assertIsInstance(repo, TestRepository)
class TestIntegration(unittest.TestCase):
"""集成测试"""
def setUp(self):
"""测试准备"""
self.user_service = UserService(StorageType.MEMORY)
def test_user_crud_operations(self):
"""测试用户CRUD操作"""
# 创建用户
user = self.user_service.create_user("测试用户", "test@example.com")
self.assertIsNotNone(user.id)
# 读取用户
retrieved_user = self.user_service.get_user(user.id)
self.assertEqual(user.id, retrieved_user.id)
# 更新用户
self.user_service.update_user(user.id, name="更新后的用户")
updated_user = self.user_service.get_user(user.id)
self.assertEqual(updated_user.name, "更新后的用户")
# 删除用户
delete_result = self.user_service.delete_user(user.id)
self.assertTrue(delete_result)
# 验证删除
deleted_user = self.user_service.get_user(user.id)
self.assertIsNone(deleted_user)
if __name__ == '__main__':
unittest.main()
7. 性能考虑与优化
7.1 单例模式的性能优化
python
import time
from functools import lru_cache
from threading import RLock
class OptimizedSingleton:
"""
优化的单例实现
结合了多种性能优化技术
"""
_instance = None
_lock = RLock() # 可重入锁,性能更好
def __init__(self):
# 延迟初始化昂贵资源
self._expensive_resource = None
def __new__(cls):
# 双重检查锁定,减少锁竞争
if cls._instance is None:
with cls._lock:
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
@property
def expensive_resource(self):
"""延迟加载昂贵资源"""
if self._expensive_resource is None:
with self._lock:
if self._expensive_resource is None:
self._expensive_resource = self._load_expensive_resource()
return self._expensive_resource
def _load_expensive_resource(self):
"""模拟加载昂贵资源"""
time.sleep(0.1) # 模拟耗时操作
return "昂贵的资源数据"
@lru_cache(maxsize=128)
def cached_operation(self, param):
"""缓存昂贵操作的结果"""
time.sleep(0.05) # 模拟耗时操作
return f"操作结果: {param}"
7.2 工厂模式的性能优化
python
from functools import lru_cache
class OptimizedFactory:
"""
优化的工厂实现
使用缓存提高性能
"""
@classmethod
@lru_cache(maxsize=128)
def create_cached_instance(cls, class_name, *args, **kwargs):
"""创建缓存实例"""
# 根据类名创建实例并缓存
import importlib
module_name, class_name = class_name.rsplit('.', 1)
module = importlib.import_module(module_name)
class_ = getattr(module, class_name)
return class_(*args, **kwargs)
class FastRepositoryFactory:
"""
快速仓库工厂
使用预注册和缓存
"""
_repository_cache = {}
@classmethod
def create_repository(cls, storage_type: StorageType, **kwargs) -> UserRepository:
# 使用缓存键
cache_key = (storage_type, tuple(sorted(kwargs.items())))
if cache_key not in cls._repository_cache:
repository = RepositoryFactory.create_repository(storage_type, **kwargs)
cls._repository_cache[cache_key] = repository
return cls._repository_cache[cache_key]
8. 总结
通过本文的深入探讨,我们学习了如何在Python中优雅地实现单例模式和工厂模式。关键要点总结如下:
8.1 单例模式要点
- 模块单例是最Pythonic的实现方式
- 装饰器提供灵活的单例控制
- 元类适合需要精细控制类创建的场景
- 考虑线程安全 和性能优化
8.2 工厂模式要点
- 简单工厂适合对象创建逻辑不复杂的场景
- 工厂方法通过子类化提供扩展性
- 抽象工厂用于创建相关对象家族
- 利用Python的动态特性实现灵活的工厂
8.3 Pythonic设计原则
- 充分利用Python语言特性
- 保持代码简洁和可读性
- 遵循"显式优于隐式"的原则
- 适当使用装饰器、元类等高级特性
8.4 实际应用建议
- 评估需求:选择最适合问题场景的模式
- 保持简单:避免过度设计
- 考虑测试:设计可测试的代码结构
- 性能考量:在性能敏感的场景进行优化
设计模式是强大的工具,但在Python中,我们应该始终以Pythonic的方式使用它们。通过结合Python的语言特性和设计模式的精髓,我们可以写出既优雅又实用的代码。
记住,最好的设计模式实现是那些既解决了问题,又保持了代码简洁性和可读性的实现。在Python的世界里,简单往往就是最好的解决方案。