# 设计模式在Chat-Room项目中的应用
## 📋 模块概述
设计模式是软件工程中解决常见问题的可复用解决方案。Chat-Room项目中应用了多种经典设计模式,本文档详细分析这些模式的实现和应用场景。
## 🎯 设计模式分类
### GoF设计模式在项目中的应用
```mermaid
graph TD
A[设计模式] --> B[创建型模式]
A --> C[结构型模式]
A --> D[行为型模式]
B --> B1[单例模式
Singleton]
B --> B2[工厂模式
Factory]
B --> B3[建造者模式
Builder]
C --> C1[适配器模式
Adapter]
C --> C2[装饰器模式
Decorator]
C --> C3[外观模式
Facade]
D --> D1[观察者模式
Observer]
D --> D2[策略模式
Strategy]
D --> D3[命令模式
Command]
D --> D4[状态模式
State]
style B1 fill:#e8f5e8
style B2 fill:#e8f5e8
style C2 fill:#e8f5e8
style D1 fill:#e8f5e8
style D2 fill:#e8f5e8
style D3 fill:#e8f5e8
```
## 🏭 创建型模式
### 1. 单例模式 (Singleton)
**应用场景**:数据库连接管理、日志管理器、配置管理器
```python
class DatabaseManager:
"""数据库管理器 - 单例模式实现"""
_instance = None
_lock = threading.Lock()
def __new__(cls, *args, **kwargs):
"""线程安全的单例实现"""
if cls._instance is None:
with cls._lock:
# 双重检查锁定
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self, db_path: str = None):
"""初始化(只执行一次)"""
if hasattr(self, '_initialized'):
return
self.db_path = db_path or "server/data/chatroom.db"
self._connection_pool = {}
self._initialized = True
@classmethod
def get_instance(cls, db_path: str = None):
"""获取单例实例"""
if cls._instance is None:
cls._instance = cls(db_path)
return cls._instance
# 使用示例
db1 = DatabaseManager.get_instance()
db2 = DatabaseManager.get_instance()
assert db1 is db2 # 确保是同一个实例
```
**Python式单例实现**:
```python
class LoggerManager:
"""使用装饰器实现的单例"""
def __init__(self):
self.loggers = {}
def get_logger(self, name: str):
if name not in self.loggers:
self.loggers[name] = self._create_logger(name)
return self.loggers[name]
# 使用模块级变量实现单例
_logger_manager = LoggerManager()
def get_logger(name: str):
"""获取日志器(模块级单例)"""
return _logger_manager.get_logger(name)
```
### 2. 工厂模式 (Factory)
**应用场景**:消息对象创建、客户端类型创建
```python
class MessageFactory:
"""消息工厂 - 根据类型创建不同的消息对象"""
# 注册消息类型
_message_classes = {
'login_request': LoginRequest,
'login_response': LoginResponse,
'chat_message': ChatMessage,
'error_message': ErrorMessage,
'file_message': FileMessage,
'admin_command': AdminCommand,
}
@classmethod
def create_message(cls, message_type: str, **kwargs) -> BaseMessage:
"""
创建消息对象
Args:
message_type: 消息类型
**kwargs: 消息参数
Returns:
消息对象实例
"""
if message_type not in cls._message_classes:
raise ValueError(f"未知消息类型: {message_type}")
message_class = cls._message_classes[message_type]
return message_class(**kwargs)
@classmethod
def register_message_type(cls, message_type: str, message_class):
"""注册新的消息类型"""
cls._message_classes[message_type] = message_class
@classmethod
def parse_from_json(cls, json_str: str) -> BaseMessage:
"""从JSON字符串解析消息"""
try:
data = json.loads(json_str)
message_type = data.get('message_type')
if not message_type:
raise ValueError("消息缺少message_type字段")
return cls.create_message(message_type, **data)
except json.JSONDecodeError as e:
raise ValueError(f"JSON解析失败: {e}")
# 使用示例
def parse_message(message_str: str) -> BaseMessage:
"""解析消息字符串"""
return MessageFactory.parse_from_json(message_str)
# 创建特定类型的消息
login_msg = MessageFactory.create_message(
'login_request',
username='alice',
password='password123'
)
```
**抽象工厂模式**:
```python
class ClientFactory:
"""客户端工厂 - 创建不同类型的客户端"""
@staticmethod
def create_client(client_type: str, **kwargs):
"""创建客户端实例"""
if client_type == 'tui':
from client.ui.app import ChatApp
return ChatApp(**kwargs)
elif client_type == 'simple':
from client.simple_client import SimpleClient
return SimpleClient(**kwargs)
elif client_type == 'test':
from test.test_client import TestClient
return TestClient(**kwargs)
else:
raise ValueError(f"未知客户端类型: {client_type}")
# 使用示例
tui_client = ClientFactory.create_client('tui', host='localhost', port=8888)
simple_client = ClientFactory.create_client('simple', host='localhost', port=8888)
```
## 🔧 结构型模式
### 1. 装饰器模式 (Decorator)
**应用场景**:日志记录、性能监控、权限检查、错误处理
```python
def log_performance(func_name: str = None):
"""性能监控装饰器"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
name = func_name or func.__name__
start_time = time.time()
try:
result = func(*args, **kwargs)
duration = time.time() - start_time
logger.debug(f"函数执行完成: {name}",
duration=duration, status="success")
return result
except Exception as e:
duration = time.time() - start_time
logger.error(f"函数执行失败: {name}",
duration=duration, status="error", error=str(e))
raise
return wrapper
return decorator
def require_authentication(func):
"""认证检查装饰器"""
@wraps(func)
def wrapper(self, *args, **kwargs):
if not hasattr(self, 'user_info') or not self.user_info:
raise AuthenticationError("需要先登录")
return func(self, *args, **kwargs)
return wrapper
def admin_required(func):
"""管理员权限检查装饰器"""
@wraps(func)
def wrapper(self, *args, **kwargs):
if not hasattr(self, 'user_info') or not self.user_info:
raise AuthenticationError("需要先登录")
if self.user_info.get('user_id') != ADMIN_USER_ID:
raise PermissionDeniedError("需要管理员权限")
return func(self, *args, **kwargs)
return wrapper
# 使用示例
class ChatManager:
@log_performance("发送消息")
@require_authentication
def send_message(self, content: str, group_id: int):
"""发送消息"""
# 消息发送逻辑
pass
@log_performance("管理员操作")
@admin_required
def ban_user(self, user_id: int):
"""禁用用户"""
# 禁用用户逻辑
pass
```
**类装饰器实现**:
```python
class RetryDecorator:
"""重试装饰器类"""
def __init__(self, max_retries: int = 3, delay: float = 1.0):
self.max_retries = max_retries
self.delay = delay
def __call__(self, func):
@wraps(func)
def wrapper(*args, **kwargs):
last_exception = None
for attempt in range(self.max_retries + 1):
try:
return func(*args, **kwargs)
except Exception as e:
last_exception = e
if attempt < self.max_retries:
logger.warning(f"函数 {func.__name__} 第{attempt + 1}次尝试失败: {e}")
time.sleep(self.delay * (2 ** attempt)) # 指数退避
else:
logger.error(f"函数 {func.__name__} 重试{self.max_retries}次后仍然失败")
raise last_exception
return wrapper
# 使用示例
@RetryDecorator(max_retries=3, delay=1.0)
def connect_to_database(self):
"""连接数据库(带重试)"""
# 数据库连接逻辑
pass
```
### 2. 适配器模式 (Adapter)
**应用场景**:不同客户端接口适配、第三方库接口适配
```python
class AIServiceAdapter:
"""AI服务适配器 - 适配不同的AI服务提供商"""
def __init__(self, ai_service):
self.ai_service = ai_service
def generate_response(self, message: str, context: List[str] = None) -> str:
"""统一的响应生成接口"""
if hasattr(self.ai_service, 'chat_completion'):
# 智谱AI接口
return self._adapt_zhipu_ai(message, context)
elif hasattr(self.ai_service, 'complete'):
# OpenAI接口
return self._adapt_openai(message, context)
else:
raise ValueError("不支持的AI服务类型")
def _adapt_zhipu_ai(self, message: str, context: List[str]) -> str:
"""适配智谱AI接口"""
messages = []
if context:
for ctx in context:
messages.append({"role": "user", "content": ctx})
messages.append({"role": "user", "content": message})
response = self.ai_service.chat_completion(messages)
return response.choices[0].message.content
def _adapt_openai(self, message: str, context: List[str]) -> str:
"""适配OpenAI接口"""
prompt = ""
if context:
prompt = "\n".join(context) + "\n"
prompt += message
response = self.ai_service.complete(prompt)
return response.choices[0].text
# 使用示例
zhipu_service = ZhipuAI(api_key="your_key")
ai_adapter = AIServiceAdapter(zhipu_service)
response = ai_adapter.generate_response("你好", ["这是上下文"])
```
## 🎭 行为型模式
### 1. 观察者模式 (Observer)
**应用场景**:消息广播、状态变化通知、事件处理
```python
class EventManager:
"""事件管理器 - 观察者模式实现"""
def __init__(self):
self._observers: Dict[str, List[Callable]] = {}
def subscribe(self, event_type: str, callback: Callable):
"""订阅事件"""
if event_type not in self._observers:
self._observers[event_type] = []
self._observers[event_type].append(callback)
def unsubscribe(self, event_type: str, callback: Callable):
"""取消订阅"""
if event_type in self._observers:
self._observers[event_type].remove(callback)
def notify(self, event_type: str, event_data: Any = None):
"""通知所有观察者"""
if event_type in self._observers:
for callback in self._observers[event_type]:
try:
callback(event_data)
except Exception as e:
logger.error(f"事件处理器执行失败: {e}")
# 全局事件管理器
event_manager = EventManager()
class ChatServer:
"""聊天服务器 - 事件发布者"""
def __init__(self):
self.event_manager = event_manager
def handle_user_login(self, user_info: dict):
"""处理用户登录"""
# 登录逻辑
self.authenticate_user(user_info)
# 发布用户登录事件
self.event_manager.notify('user_login', user_info)
def handle_message_sent(self, message: ChatMessage):
"""处理消息发送"""
# 保存消息
self.save_message(message)
# 发布消息发送事件
self.event_manager.notify('message_sent', message)
class UserStatusTracker:
"""用户状态跟踪器 - 观察者"""
def __init__(self):
event_manager.subscribe('user_login', self.on_user_login)
event_manager.subscribe('user_logout', self.on_user_logout)
def on_user_login(self, user_info: dict):
"""用户登录事件处理"""
logger.info(f"用户上线: {user_info['username']}")
self.update_user_status(user_info['user_id'], True)
def on_user_logout(self, user_info: dict):
"""用户登出事件处理"""
logger.info(f"用户下线: {user_info['username']}")
self.update_user_status(user_info['user_id'], False)
class MessageBroadcaster:
"""消息广播器 - 观察者"""
def __init__(self, user_manager):
self.user_manager = user_manager
event_manager.subscribe('message_sent', self.on_message_sent)
def on_message_sent(self, message: ChatMessage):
"""消息发送事件处理"""
# 广播消息给聊天组成员
self.broadcast_to_group(message)
```
### 2. 策略模式 (Strategy)
**应用场景**:消息处理策略、认证策略、文件存储策略
```python
class MessageProcessingStrategy:
"""消息处理策略接口"""
def process(self, message: BaseMessage, context: dict) -> bool:
"""处理消息"""
raise NotImplementedError
class TextMessageStrategy(MessageProcessingStrategy):
"""文本消息处理策略"""
def process(self, message: ChatMessage, context: dict) -> bool:
# 文本消息处理逻辑
self.validate_text_content(message.content)
self.save_to_database(message)
self.broadcast_to_group(message, context)
return True
def validate_text_content(self, content: str):
"""验证文本内容"""
if len(content) > 2000:
raise ValidationError("消息内容过长")
# 敏感词过滤
if self.contains_sensitive_words(content):
raise ValidationError("消息包含敏感词")
class FileMessageStrategy(MessageProcessingStrategy):
"""文件消息处理策略"""
def process(self, message: FileMessage, context: dict) -> bool:
# 文件消息处理逻辑
self.validate_file(message)
self.save_file_metadata(message)
self.notify_file_upload(message, context)
return True
def validate_file(self, message: FileMessage):
"""验证文件"""
if message.file_size > 50 * 1024 * 1024: # 50MB
raise ValidationError("文件大小超过限制")
allowed_types = ['.txt', '.jpg', '.png', '.pdf', '.doc']
if not any(message.filename.endswith(ext) for ext in allowed_types):
raise ValidationError("不支持的文件类型")
class AdminCommandStrategy(MessageProcessingStrategy):
"""管理员命令处理策略"""
def process(self, message: AdminCommand, context: dict) -> bool:
# 管理员命令处理逻辑
self.validate_admin_permission(context)
self.execute_admin_command(message)
self.log_admin_operation(message, context)
return True
class MessageProcessor:
"""消息处理器 - 策略模式上下文"""
def __init__(self):
self.strategies = {
'chat_message': TextMessageStrategy(),
'file_message': FileMessageStrategy(),
'admin_command': AdminCommandStrategy(),
}
def process_message(self, message: BaseMessage, context: dict) -> bool:
"""处理消息"""
strategy = self.strategies.get(message.message_type)
if not strategy:
raise ValueError(f"不支持的消息类型: {message.message_type}")
return strategy.process(message, context)
def register_strategy(self, message_type: str, strategy: MessageProcessingStrategy):
"""注册新的处理策略"""
self.strategies[message_type] = strategy
```
### 3. 命令模式 (Command)
**应用场景**:管理员命令、撤销操作、批量操作
```python
class Command:
"""命令接口"""
def execute(self) -> bool:
"""执行命令"""
raise NotImplementedError
def undo(self) -> bool:
"""撤销命令"""
raise NotImplementedError
def get_description(self) -> str:
"""获取命令描述"""
raise NotImplementedError
class BanUserCommand(Command):
"""禁用用户命令"""
def __init__(self, user_manager, user_id: int):
self.user_manager = user_manager
self.user_id = user_id
self.was_banned = False
def execute(self) -> bool:
"""执行禁用"""
try:
user_info = self.user_manager.get_user_by_id(self.user_id)
self.was_banned = user_info.get('is_banned', False)
if not self.was_banned:
self.user_manager.ban_user(self.user_id)
logger.info(f"用户被禁用: {self.user_id}")
return True
return False
except Exception as e:
logger.error(f"禁用用户失败: {e}")
return False
def undo(self) -> bool:
"""撤销禁用"""
try:
if not self.was_banned:
self.user_manager.free_user(self.user_id)
logger.info(f"用户禁用被撤销: {self.user_id}")
return True
return False
except Exception as e:
logger.error(f"撤销禁用失败: {e}")
return False
def get_description(self) -> str:
return f"禁用用户 {self.user_id}"
class DeleteChatGroupCommand(Command):
"""删除聊天组命令"""
def __init__(self, chat_manager, group_id: int):
self.chat_manager = chat_manager
self.group_id = group_id
self.backup_data = None
def execute(self) -> bool:
"""执行删除"""
try:
# 备份数据用于撤销
self.backup_data = self.chat_manager.backup_chat_group(self.group_id)
self.chat_manager.delete_chat_group(self.group_id)
logger.info(f"聊天组被删除: {self.group_id}")
return True
except Exception as e:
logger.error(f"删除聊天组失败: {e}")
return False
def undo(self) -> bool:
"""撤销删除"""
try:
if self.backup_data:
self.chat_manager.restore_chat_group(self.backup_data)
logger.info(f"聊天组删除被撤销: {self.group_id}")
return True
return False
except Exception as e:
logger.error(f"撤销删除失败: {e}")
return False
def get_description(self) -> str:
return f"删除聊天组 {self.group_id}"
class CommandInvoker:
"""命令调用器"""
def __init__(self):
self.command_history: List[Command] = []
self.current_position = -1
def execute_command(self, command: Command) -> bool:
"""执行命令"""
success = command.execute()
if success:
# 清除当前位置之后的历史
self.command_history = self.command_history[:self.current_position + 1]
# 添加新命令
self.command_history.append(command)
self.current_position += 1
logger.info(f"命令执行成功: {command.get_description()}")
return success
def undo_last_command(self) -> bool:
"""撤销最后一个命令"""
if self.current_position >= 0:
command = self.command_history[self.current_position]
success = command.undo()
if success:
self.current_position -= 1
logger.info(f"命令撤销成功: {command.get_description()}")
return success
return False
def redo_command(self) -> bool:
"""重做命令"""
if self.current_position < len(self.command_history) - 1:
self.current_position += 1
command = self.command_history[self.current_position]
success = command.execute()
if success:
logger.info(f"命令重做成功: {command.get_description()}")
else:
self.current_position -= 1
return success
return False
def get_command_history(self) -> List[str]:
"""获取命令历史"""
return [cmd.get_description() for cmd in self.command_history]
# 使用示例
class AdminManager:
def __init__(self):
self.command_invoker = CommandInvoker()
def ban_user(self, user_id: int) -> bool:
"""禁用用户"""
command = BanUserCommand(self.user_manager, user_id)
return self.command_invoker.execute_command(command)
def undo_last_operation(self) -> bool:
"""撤销最后一个操作"""
return self.command_invoker.undo_last_command()
```
## 💡 学习要点
### 设计模式的价值
1. **代码复用**:提供经过验证的解决方案
2. **可维护性**:清晰的结构和职责分离
3. **可扩展性**:易于添加新功能和修改现有功能
4. **团队协作**:统一的设计语言和思维模式
### 模式选择原则
1. **问题导向**:根据实际问题选择合适的模式
2. **简单优先**:不要过度设计,保持简单
3. **组合使用**:多个模式可以组合使用
4. **演进式设计**:随着需求变化逐步引入模式
### Python特色实现
1. **装饰器**:Python原生支持装饰器模式
2. **鸭子类型**:利用动态类型简化接口设计
3. **元类**:高级模式可以使用元类实现
4. **上下文管理器**:资源管理的Python式实现
## 🤔 思考题
1. **如何避免设计模式的滥用?**
- 遵循YAGNI原则(You Aren't Gonna Need It)
- 重构时引入模式而非预先设计
- 关注问题本质而非模式本身
2. **如何在团队中推广设计模式?**
- 代码审查中讨论模式应用
- 编写模式应用文档和示例
- 渐进式引入,从简单模式开始
3. **如何评估模式应用的效果?**
- 代码可读性和可维护性
- 功能扩展的便利性
- 团队开发效率
---
**下一步**:学习测试策略 → [testing.md](./testing.md)