python 单例模式

44 阅读2分钟

单例模式

单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。

单例模式的核心思想

限制类的实例化次数,确保在整个应用程序中,某个类只有一个对象实例存在。

单例模式应用场景

  1. 配置管理
  2. 数据库连接池
  3. 日志记录器
  4. 缓存管理器
  5. 应用上下文/状态管理

代码实现示例(配置管理)

config_reader.py

import os
from typing import Optional, Any, Dict
from pathlib import Path
import yaml
from dotenv import load_dotenv


load_dotenv()

class ConfigError(Exception):
    """自定义配置异常"""
    pass

class ConfigReader:
    _instance = None  # 类变量,用于存储唯一实例
    def __new__(cls, *args, **kwargs): #  __new__方法控制实例创建
        if not cls._instance: # 如果实例不存在
            cls._instance = super().__new__(cls) # 调用父类的__new__方法来创建实例
            cls._instance._initialized = False # 防止重复初始化,在新创建的实例上设置一个标记,表示"这个实例还没有被初始化"
        return cls._instance

    def __init__(self,config_path:str=Path(__file__).parent.parent / "environments.yml",
                 env:Optional[str]=None
                 ):
        if self._initialized: # 如果已经初始化了,直接返回
            return
        # 实例变量初始化
        self._config: Dict[str,Any] = {}
        self._env: Optional[str] = env or os.getenv("ENV","test") # 优先级链:参数 > 环境变量 > 默认值
        self._config_path = Path(config_path)

        try:
            self._load_config()
            self._process_environment()
        except Exception as e:
            raise ConfigError(f"Config initialization failed: {str(e)}") from e

        self._initialized = True


    def _load_config(self) -> None:
        """加载基础配置文件"""
        if not self._config_path.exists():
            raise FileNotFoundError(f"Config file not found: {self._config_path}")
        try:
            with open(self._config_path, 'r') as f:
                self._config = yaml.safe_load(f) or {}
        except yaml.YAMLError as e:
            raise ConfigError(f"YAML parsing error: {str(e)}")

    def _process_environment(self) -> None:
        """处理环境特定配置"""
        pass

    

config = ConfigReader()

environments.yml

environments:
  TS:
    project: tsing
    sys:
      host: 192.168.1.1
      user: liming
      pwd: aa123456
      redis_port: 5501
      redis_pwd: west5501
  RZ:
    project: rzing
    sys:
      host: 192.168.1.2
      user: limingxia
      pwd: aa1234567
      redis_port: 5502
      redis_pwd: west5502

.env

ENV=TS

使用示例

example.py

from other.config_reader import config


PROJECT = config.get("project", required=True)
print(PROJECT)
REDIS_PORT = config.get("redis_port", default="6379")
print(REDIS_PORT))