# Chat-Room中的设计模式 ## 🎯 学习目标 通过本节学习,您将能够: - 理解设计模式在实际项目中的应用 - 识别Chat-Room项目中使用的设计模式 - 掌握常用设计模式的实现方法 - 学会在自己的项目中应用设计模式 - 理解设计模式如何提高代码质量 ## 📖 设计模式概述 设计模式是软件设计中常见问题的典型解决方案。它们就像预先制作的蓝图,可以定制来解决代码中的重复设计问题。 ### Chat-Room项目中的设计模式分布 ```mermaid graph TD A[Chat-Room设计模式] --> B[创建型模式] A --> C[结构型模式] A --> D[行为型模式] B --> B1[单例模式
数据库连接] B --> B2[工厂模式
消息创建] B --> B3[建造者模式
配置构建] C --> C1[适配器模式
协议转换] C --> C2[装饰器模式
功能增强] C --> C3[外观模式
API简化] D --> D1[观察者模式
事件通知] D --> D2[策略模式
消息处理] D --> D3[命令模式
操作封装] style A fill:#e8f5e8 style B fill:#fff3cd style C fill:#f8d7da style D fill:#e1f5fe ``` ## 🏗️ 创建型模式 ### 1. 单例模式 - 数据库连接管理 **应用场景**:确保数据库连接管理器在整个应用中只有一个实例。 ```python """ 单例模式实现 - 数据库连接管理器 确保整个应用只有一个数据库连接实例 """ import sqlite3 import threading from typing import Optional class DatabaseManager: """ 数据库管理器单例类 使用单例模式确保整个应用只有一个数据库连接实例, 避免多个连接导致的资源浪费和数据不一致问题。 """ _instance: Optional['DatabaseManager'] = None _lock = threading.Lock() def __new__(cls, db_path: str = "chatroom.db"): """ 创建单例实例 使用双重检查锁定模式确保线程安全的单例创建 """ if cls._instance is None: with cls._lock: # 双重检查,防止多线程环境下创建多个实例 if cls._instance is None: cls._instance = super().__new__(cls) cls._instance._initialized = False return cls._instance def __init__(self, db_path: str = "chatroom.db"): """初始化数据库连接""" if self._initialized: return self.db_path = db_path self.connection: Optional[sqlite3.Connection] = None self._lock = threading.Lock() self._connect() self._initialized = True def _connect(self) -> None: """建立数据库连接""" try: self.connection = sqlite3.connect( self.db_path, check_same_thread=False ) self.connection.row_factory = sqlite3.Row print(f"数据库连接已建立: {self.db_path}") except Exception as e: print(f"数据库连接失败: {e}") raise def get_connection(self) -> sqlite3.Connection: """获取数据库连接""" if self.connection is None: with self._lock: if self.connection is None: self._connect() return self.connection def execute_query(self, query: str, params: tuple = ()) -> list: """执行查询语句""" with self._lock: cursor = self.get_connection().cursor() cursor.execute(query, params) return cursor.fetchall() def execute_update(self, query: str, params: tuple = ()) -> int: """执行更新语句""" with self._lock: cursor = self.get_connection().cursor() cursor.execute(query, params) self.connection.commit() return cursor.rowcount def close(self) -> None: """关闭数据库连接""" if self.connection: self.connection.close() self.connection = None print("数据库连接已关闭") # 使用示例 def demonstrate_singleton_pattern(): """演示单例模式的使用""" print("=== 单例模式演示 ===") # 创建多个实例,实际上都是同一个对象 db1 = DatabaseManager("chatroom.db") db2 = DatabaseManager("another.db") # 参数会被忽略 db3 = DatabaseManager() # 验证是否为同一个实例 print(f"db1 is db2: {db1 is db2}") # True print(f"db2 is db3: {db2 is db3}") # True print(f"实例ID: db1={id(db1)}, db2={id(db2)}, db3={id(db3)}") ``` ### 2. 工厂模式 - 消息对象创建 **应用场景**:根据不同的消息类型创建相应的消息对象。 ```python """ 工厂模式实现 - 消息对象创建 根据消息类型创建不同的消息对象 """ from abc import ABC, abstractmethod from enum import Enum from typing import Dict, Any, Optional from dataclasses import dataclass import time class MessageType(Enum): """消息类型枚举""" CHAT = "chat" LOGIN = "login" LOGOUT = "logout" FILE_TRANSFER = "file_transfer" SYSTEM = "system" ERROR = "error" @dataclass class BaseMessage(ABC): """消息基类""" message_type: MessageType sender: Optional[str] = None timestamp: float = None def __post_init__(self): if self.timestamp is None: self.timestamp = time.time() @abstractmethod def to_dict(self) -> Dict[str, Any]: """转换为字典格式""" pass @abstractmethod def validate(self) -> bool: """验证消息格式""" pass @dataclass class ChatMessage(BaseMessage): """聊天消息""" content: str = "" target_user: Optional[str] = None chat_group: Optional[str] = None def __post_init__(self): super().__post_init__() self.message_type = MessageType.CHAT def to_dict(self) -> Dict[str, Any]: return { "type": self.message_type.value, "sender": self.sender, "content": self.content, "target_user": self.target_user, "chat_group": self.chat_group, "timestamp": self.timestamp } def validate(self) -> bool: return bool(self.content.strip() and self.sender) @dataclass class LoginMessage(BaseMessage): """登录消息""" username: str = "" password: str = "" def __post_init__(self): super().__post_init__() self.message_type = MessageType.LOGIN def to_dict(self) -> Dict[str, Any]: return { "type": self.message_type.value, "username": self.username, "password": self.password, "timestamp": self.timestamp } def validate(self) -> bool: return bool(self.username.strip() and self.password.strip()) @dataclass class FileTransferMessage(BaseMessage): """文件传输消息""" filename: str = "" file_size: int = 0 file_hash: str = "" chunk_data: Optional[bytes] = None def __post_init__(self): super().__post_init__() self.message_type = MessageType.FILE_TRANSFER def to_dict(self) -> Dict[str, Any]: return { "type": self.message_type.value, "sender": self.sender, "filename": self.filename, "file_size": self.file_size, "file_hash": self.file_hash, "timestamp": self.timestamp } def validate(self) -> bool: return bool(self.filename.strip() and self.file_size > 0) class MessageFactory: """ 消息工厂类 使用工厂模式根据消息类型创建相应的消息对象, 简化消息对象的创建过程并确保类型安全。 """ # 消息类型到类的映射 _message_classes = { MessageType.CHAT: ChatMessage, MessageType.LOGIN: LoginMessage, MessageType.FILE_TRANSFER: FileTransferMessage, } @classmethod def create_message(cls, message_type: MessageType, **kwargs) -> Optional[BaseMessage]: """ 创建消息对象 Args: message_type: 消息类型 **kwargs: 消息参数 Returns: BaseMessage: 创建的消息对象,如果类型不支持则返回None """ message_class = cls._message_classes.get(message_type) if message_class is None: print(f"不支持的消息类型: {message_type}") return None try: message = message_class(**kwargs) if message.validate(): return message else: print(f"消息验证失败: {kwargs}") return None except Exception as e: print(f"创建消息对象失败: {e}") return None @classmethod def create_from_dict(cls, data: Dict[str, Any]) -> Optional[BaseMessage]: """ 从字典创建消息对象 Args: data: 消息数据字典 Returns: BaseMessage: 创建的消息对象 """ try: message_type_str = data.get("type") if not message_type_str: return None message_type = MessageType(message_type_str) # 移除type字段,避免重复传递 message_data = {k: v for k, v in data.items() if k != "type"} return cls.create_message(message_type, **message_data) except ValueError as e: print(f"无效的消息类型: {message_type_str}") return None except Exception as e: print(f"从字典创建消息失败: {e}") return None @classmethod def register_message_type(cls, message_type: MessageType, message_class: type) -> None: """ 注册新的消息类型 Args: message_type: 消息类型 message_class: 消息类 """ cls._message_classes[message_type] = message_class print(f"注册消息类型: {message_type.value} -> {message_class.__name__}") # 使用示例 def demonstrate_factory_pattern(): """演示工厂模式的使用""" print("\n=== 工厂模式演示 ===") # 创建不同类型的消息 chat_msg = MessageFactory.create_message( MessageType.CHAT, sender="张三", content="Hello, World!", target_user="李四" ) login_msg = MessageFactory.create_message( MessageType.LOGIN, username="test_user", password="password123" ) file_msg = MessageFactory.create_message( MessageType.FILE_TRANSFER, sender="张三", filename="document.pdf", file_size=1024000, file_hash="abc123def456" ) # 打印消息信息 messages = [chat_msg, login_msg, file_msg] for msg in messages: if msg: print(f"消息类型: {msg.message_type.value}") print(f"消息内容: {msg.to_dict()}") print(f"验证结果: {msg.validate()}") print("-" * 40) # 从字典创建消息 dict_data = { "type": "chat", "sender": "王五", "content": "这是从字典创建的消息", "timestamp": time.time() } dict_msg = MessageFactory.create_from_dict(dict_data) if dict_msg: print(f"从字典创建的消息: {dict_msg.to_dict()}") ``` ## 🔗 结构型模式 ### 1. 适配器模式 - 协议转换 **应用场景**:将不同的网络协议或数据格式转换为统一的内部格式。 ```python """ 适配器模式实现 - 协议转换 将不同的网络协议转换为统一的内部消息格式 """ from abc import ABC, abstractmethod from typing import Dict, Any import json import xml.etree.ElementTree as ET class MessageProtocol(ABC): """消息协议接口""" @abstractmethod def serialize(self, data: Dict[str, Any]) -> str: """序列化数据""" pass @abstractmethod def deserialize(self, data: str) -> Dict[str, Any]: """反序列化数据""" pass class JSONProtocol(MessageProtocol): """JSON协议实现""" def serialize(self, data: Dict[str, Any]) -> str: return json.dumps(data, ensure_ascii=False) def deserialize(self, data: str) -> Dict[str, Any]: return json.loads(data) class XMLProtocol(MessageProtocol): """XML协议实现(第三方协议,接口不兼容)""" def to_xml(self, data: Dict[str, Any]) -> str: """转换为XML格式""" root = ET.Element("message") for key, value in data.items(): elem = ET.SubElement(root, key) elem.text = str(value) return ET.tostring(root, encoding='unicode') def from_xml(self, xml_data: str) -> Dict[str, Any]: """从XML格式解析""" root = ET.fromstring(xml_data) return {child.tag: child.text for child in root} class XMLProtocolAdapter(MessageProtocol): """ XML协议适配器 将XMLProtocol的接口适配为MessageProtocol接口, 使其能够与系统的其他部分兼容。 """ def __init__(self, xml_protocol: XMLProtocol): self.xml_protocol = xml_protocol def serialize(self, data: Dict[str, Any]) -> str: """适配serialize方法""" return self.xml_protocol.to_xml(data) def deserialize(self, data: str) -> Dict[str, Any]: """适配deserialize方法""" return self.xml_protocol.from_xml(data) class ProtocolManager: """协议管理器""" def __init__(self): self.protocols: Dict[str, MessageProtocol] = {} self._setup_protocols() def _setup_protocols(self): """设置支持的协议""" # 直接支持的协议 self.protocols["json"] = JSONProtocol() # 通过适配器支持的协议 xml_protocol = XMLProtocol() self.protocols["xml"] = XMLProtocolAdapter(xml_protocol) def send_message(self, protocol_name: str, data: Dict[str, Any]) -> str: """使用指定协议发送消息""" protocol = self.protocols.get(protocol_name) if not protocol: raise ValueError(f"不支持的协议: {protocol_name}") return protocol.serialize(data) def receive_message(self, protocol_name: str, data: str) -> Dict[str, Any]: """使用指定协议接收消息""" protocol = self.protocols.get(protocol_name) if not protocol: raise ValueError(f"不支持的协议: {protocol_name}") return protocol.deserialize(data) # 使用示例 def demonstrate_adapter_pattern(): """演示适配器模式的使用""" print("\n=== 适配器模式演示 ===") manager = ProtocolManager() # 测试数据 test_data = { "type": "chat", "sender": "张三", "content": "Hello, World!", "timestamp": "1234567890" } # 使用JSON协议 json_data = manager.send_message("json", test_data) print(f"JSON格式: {json_data}") received_json = manager.receive_message("json", json_data) print(f"JSON解析: {received_json}") # 使用XML协议(通过适配器) xml_data = manager.send_message("xml", test_data) print(f"XML格式: {xml_data}") received_xml = manager.receive_message("xml", xml_data) print(f"XML解析: {received_xml}") ``` ## 🎭 行为型模式 ### 1. 观察者模式 - 事件通知系统 **应用场景**:当用户状态发生变化时,通知所有相关的组件。 ```python """ 观察者模式实现 - 事件通知系统 当用户状态或消息事件发生时,通知所有订阅的观察者 """ from abc import ABC, abstractmethod from typing import List, Dict, Any from enum import Enum class EventType(Enum): """事件类型""" USER_LOGIN = "user_login" USER_LOGOUT = "user_logout" MESSAGE_RECEIVED = "message_received" FILE_UPLOADED = "file_uploaded" ERROR_OCCURRED = "error_occurred" class Observer(ABC): """观察者接口""" @abstractmethod def update(self, event_type: EventType, data: Dict[str, Any]) -> None: """处理事件通知""" pass class Subject(ABC): """主题接口""" @abstractmethod def attach(self, observer: Observer) -> None: """添加观察者""" pass @abstractmethod def detach(self, observer: Observer) -> None: """移除观察者""" pass @abstractmethod def notify(self, event_type: EventType, data: Dict[str, Any]) -> None: """通知所有观察者""" pass class EventManager(Subject): """ 事件管理器 实现观察者模式的主题角色,管理所有观察者并负责事件通知。 支持按事件类型订阅,提高通知效率。 """ def __init__(self): # 按事件类型分组的观察者列表 self._observers: Dict[EventType, List[Observer]] = {} # 全局观察者列表(订阅所有事件) self._global_observers: List[Observer] = [] def attach(self, observer: Observer, event_types: List[EventType] = None) -> None: """ 添加观察者 Args: observer: 观察者对象 event_types: 订阅的事件类型列表,如果为None则订阅所有事件 """ if event_types is None: # 订阅所有事件 if observer not in self._global_observers: self._global_observers.append(observer) print(f"观察者 {observer.__class__.__name__} 订阅了所有事件") else: # 订阅特定事件 for event_type in event_types: if event_type not in self._observers: self._observers[event_type] = [] if observer not in self._observers[event_type]: self._observers[event_type].append(observer) print(f"观察者 {observer.__class__.__name__} 订阅了事件 {event_type.value}") def detach(self, observer: Observer, event_types: List[EventType] = None) -> None: """ 移除观察者 Args: observer: 观察者对象 event_types: 取消订阅的事件类型列表,如果为None则取消所有订阅 """ if event_types is None: # 取消所有订阅 if observer in self._global_observers: self._global_observers.remove(observer) for event_type in self._observers: if observer in self._observers[event_type]: self._observers[event_type].remove(observer) print(f"观察者 {observer.__class__.__name__} 取消了所有订阅") else: # 取消特定事件订阅 for event_type in event_types: if event_type in self._observers and observer in self._observers[event_type]: self._observers[event_type].remove(observer) print(f"观察者 {observer.__class__.__name__} 取消了事件 {event_type.value} 的订阅") def notify(self, event_type: EventType, data: Dict[str, Any]) -> None: """ 通知观察者 Args: event_type: 事件类型 data: 事件数据 """ print(f"触发事件: {event_type.value}") # 通知全局观察者 for observer in self._global_observers: try: observer.update(event_type, data) except Exception as e: print(f"通知观察者 {observer.__class__.__name__} 时出错: {e}") # 通知特定事件的观察者 if event_type in self._observers: for observer in self._observers[event_type]: try: observer.update(event_type, data) except Exception as e: print(f"通知观察者 {observer.__class__.__name__} 时出错: {e}") # 具体观察者实现 class UINotificationObserver(Observer): """UI通知观察者""" def update(self, event_type: EventType, data: Dict[str, Any]) -> None: """更新UI显示""" if event_type == EventType.USER_LOGIN: username = data.get("username", "未知用户") print(f"[UI] 用户 {username} 已登录") elif event_type == EventType.MESSAGE_RECEIVED: sender = data.get("sender", "未知发送者") content = data.get("content", "") print(f"[UI] 收到来自 {sender} 的消息: {content}") elif event_type == EventType.ERROR_OCCURRED: error_msg = data.get("error", "未知错误") print(f"[UI] 错误提示: {error_msg}") class LoggingObserver(Observer): """日志记录观察者""" def update(self, event_type: EventType, data: Dict[str, Any]) -> None: """记录日志""" print(f"[LOG] 事件: {event_type.value}, 数据: {data}") class StatisticsObserver(Observer): """统计观察者""" def __init__(self): self.stats = { "login_count": 0, "message_count": 0, "error_count": 0 } def update(self, event_type: EventType, data: Dict[str, Any]) -> None: """更新统计数据""" if event_type == EventType.USER_LOGIN: self.stats["login_count"] += 1 elif event_type == EventType.MESSAGE_RECEIVED: self.stats["message_count"] += 1 elif event_type == EventType.ERROR_OCCURRED: self.stats["error_count"] += 1 print(f"[STATS] 当前统计: {self.stats}") # 使用示例 def demonstrate_observer_pattern(): """演示观察者模式的使用""" print("\n=== 观察者模式演示 ===") # 创建事件管理器 event_manager = EventManager() # 创建观察者 ui_observer = UINotificationObserver() log_observer = LoggingObserver() stats_observer = StatisticsObserver() # 订阅事件 event_manager.attach(ui_observer, [EventType.USER_LOGIN, EventType.MESSAGE_RECEIVED]) event_manager.attach(log_observer) # 订阅所有事件 event_manager.attach(stats_observer, [EventType.USER_LOGIN, EventType.MESSAGE_RECEIVED, EventType.ERROR_OCCURRED]) print("\n--- 触发事件 ---") # 触发用户登录事件 event_manager.notify(EventType.USER_LOGIN, { "username": "张三", "user_id": "user_001", "login_time": "2024-01-01 10:00:00" }) # 触发消息接收事件 event_manager.notify(EventType.MESSAGE_RECEIVED, { "sender": "李四", "content": "Hello, 张三!", "timestamp": "2024-01-01 10:01:00" }) # 触发错误事件 event_manager.notify(EventType.ERROR_OCCURRED, { "error": "网络连接超时", "error_code": "NETWORK_TIMEOUT" }) # 运行所有演示 if __name__ == "__main__": demonstrate_singleton_pattern() demonstrate_factory_pattern() demonstrate_adapter_pattern() demonstrate_observer_pattern() ``` ## 📊 设计模式的优势 ### 1. 代码复用性 - 提供经过验证的解决方案 - 减少重复代码的编写 - 提高开发效率 ### 2. 可维护性 - 代码结构清晰,易于理解 - 修改和扩展更加容易 - 降低维护成本 ### 3. 可扩展性 - 支持功能的灵活扩展 - 新需求的快速实现 - 系统架构的平滑演进 ## 📋 学习检查清单 完成本节学习后,请确认您能够: - [ ] 理解设计模式的基本概念 - [ ] 识别Chat-Room项目中的设计模式 - [ ] 实现单例、工厂、适配器、观察者模式 - [ ] 理解每种模式的适用场景 - [ ] 在自己的项目中应用设计模式 ## 🚀 下一步 完成设计模式学习后,请继续学习: - [项目组织原则](project-organization.md) - [模块化设计思想](modular-design.md) --- ## 📖 导航 ⬅️ **上一节:** [Pep8 Standards](pep8-standards.md) 📚 **返回:** [第4章:软件工程](README.md) 🏠 **主页:** [学习路径总览](../README.md) **掌握设计模式,构建优雅的软件架构!** 🏗️