第一章:单例模式 - 武林中的孤高剑客

故事延续:孤高剑客的独门绝技

在架构老人宣布华山论剑开始后,Singleton(单例模式)率先踏出一步,他那如雪的白衣在圣殿的流光中显得格外耀眼。周围的高手们都不禁为他那"唯我独尊"的气场所震慑。

“既然盟主有令,那就由在下先来展示独门绝技吧。” Singleton声音清冷,却带着不容置疑的权威,“在软件江湖中,有些存在天生就该独一无二——配置管理器、线程池、日志系统、数据库连接池…这些核心资源若被随意创建,必将导致系统混乱!”

单例模式的武学精要

核心心法

Singleton缓缓抬起右手,掌心浮现出一团旋转的二进制代码:“我的武学核心只有八字真言——确保一类仅存一实例。通过私有化构造函数,让外界无法随意创建,再提供统一的访问入口,让天下英雄都能找到这唯一的我。”

C++ 代码实战
#include <iostream>
  #include <mutex>
    #include <memory>
      // 单例模式 - 懒汉式(线程安全版本)
      class Singleton {
      private:
      // 私有的静态实例指针
      static Singleton* instance;
      static std::mutex mutex_;
      // 私有构造函数,防止外部实例化
      Singleton() {
      std::cout << "Singleton 实例被创建!" << std::endl;
      }
      // 私有拷贝构造和赋值操作,防止复制
      Singleton(const Singleton&) = delete;
      Singleton& operator=(const Singleton&) = delete;
      public:
      // 公有静态方法,提供全局访问点
      static Singleton* getInstance() {
      std::lock_guard<std::mutex> lock(mutex_);
        if (instance == nullptr) {
        instance = new Singleton();
        }
        return instance;
        }
        // 业务方法示例
        void doSomething() {
        std::cout << "Singleton 正在处理业务..." << std::endl;
        }
        // 释放资源
        static void destroyInstance() {
        std::lock_guard<std::mutex> lock(mutex_);
          if (instance != nullptr) {
          delete instance;
          instance = nullptr;
          std::cout << "Singleton 实例已被销毁!" << std::endl;
          }
          }
          };
          // 静态成员初始化
          Singleton* Singleton::instance = nullptr;
          std::mutex Singleton::mutex_;
          // 现代C++推荐写法 - 使用局部静态变量(C++11线程安全)
          class ModernSingleton {
          private:
          ModernSingleton() {
          std::cout << "ModernSingleton 实例被创建!" << std::endl;
          }
          public:
          static ModernSingleton& getInstance() {
          static ModernSingleton instance;  // C++11保证线程安全
          return instance;
          }
          void doSomething() {
          std::cout << "ModernSingleton 正在处理业务..." << std::endl;
          }
          // 删除拷贝构造和赋值操作
          ModernSingleton(const ModernSingleton&) = delete;
          ModernSingleton& operator=(const ModernSingleton&) = delete;
          };
          // 模板单例 - 让单例模式更通用
          template<typename T>
            class TemplateSingleton {
            protected:
            TemplateSingleton() = default;
            virtual ~TemplateSingleton() = default;
            public:
            static T& getInstance() {
            static T instance;
            return instance;
            }
            TemplateSingleton(const TemplateSingleton&) = delete;
            TemplateSingleton& operator=(const TemplateSingleton&) = delete;
            };
            // 具体业务类使用模板单例
            class ConfigurationManager : public TemplateSingleton<ConfigurationManager> {
              friend class TemplateSingleton<ConfigurationManager>;
                private:
                std::string configData;
                ConfigurationManager() {
                configData = "默认配置数据";
                std::cout << "配置管理器初始化完成!" << std::endl;
                }
                public:
                void loadConfig(const std::string& data) {
                configData = data;
                std::cout << "配置已加载: " << configData << std::endl;
                }
                std::string getConfig() const {
                return configData;
                }
                };

UML 武功秘籍图

Singleton
-static Singleton* instance
-static mutex mutex_
-Singleton()
+static Singleton* getInstance()
+doSomething() : void
+static destroyInstance()
ModernSingleton
-ModernSingleton()
+static getInstance()
+doSomething() : void
TemplateSingleton<T>
#TemplateSingleton()
+static getInstance()
ConfigurationManager
-string configData
-ConfigurationManager()
+loadConfig(string) : void
+getConfig() : string

实战演练:日志系统的单例实现

#include <fstream>
  #include <string>
    #include <chrono>
      #include <iomanip>
        // 实战案例:日志系统单例
        class Logger : public TemplateSingleton<Logger> {
          friend class TemplateSingleton<Logger>;
            private:
            std::ofstream logFile;
            bool enabled;
            Logger() : enabled(true) {
            logFile.open("application.log", std::ios::app);
            if (!logFile.is_open()) {
            std::cerr << "无法打开日志文件!" << std::endl;
            enabled = false;
            }
            }
            ~Logger() {
            if (logFile.is_open()) {
            logFile.close();
            }
            }
            std::string getCurrentTime() {
            auto now = std::chrono::system_clock::now();
            auto time_t = std::chrono::system_clock::to_time_t(now);
            std::stringstream ss;
            ss << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S");
            return ss.str();
            }
            public:
            void log(const std::string& message, const std::string& level = "INFO") {
            if (!enabled) return;
            std::string logEntry = "[" + getCurrentTime() + "] " +
            "[" + level + "] " + message;
            std::cout << logEntry << std::endl;
            if (logFile.is_open()) {
            logFile << logEntry << std::endl;
            logFile.flush();
            }
            }
            void error(const std::string& message) {
            log(message, "ERROR");
            }
            void warn(const std::string& message) {
            log(message, "WARN");
            }
            void info(const std::string& message) {
            log(message, "INFO");
            }
            };
            // 数据库连接池单例
            class DatabaseConnectionPool {
            private:
            static DatabaseConnectionPool* instance;
            static std::mutex mutex_;
            int maxConnections;
            int currentConnections;
            DatabaseConnectionPool() : maxConnections(10), currentConnections(0) {
            std::cout << "数据库连接池初始化,最大连接数: " << maxConnections << std::endl;
            }
            public:
            static DatabaseConnectionPool* getInstance() {
            std::lock_guard<std::mutex> lock(mutex_);
              if (instance == nullptr) {
              instance = new DatabaseConnectionPool();
              }
              return instance;
              }
              bool acquireConnection() {
              std::lock_guard<std::mutex> lock(mutex_);
                if (currentConnections < maxConnections) {
                currentConnections++;
                std::cout << "获取数据库连接成功,当前连接数: " << currentConnections << std::endl;
                return true;
                }
                std::cout << "获取数据库连接失败,连接池已满!" << std::endl;
                return false;
                }
                void releaseConnection() {
                std::lock_guard<std::mutex> lock(mutex_);
                  if (currentConnections > 0) {
                  currentConnections--;
                  std::cout << "释放数据库连接,当前连接数: " << currentConnections << std::endl;
                  }
                  }
                  static void destroyInstance() {
                  std::lock_guard<std::mutex> lock(mutex_);
                    if (instance != nullptr) {
                    delete instance;
                    instance = nullptr;
                    }
                    }
                    };
                    DatabaseConnectionPool* DatabaseConnectionPool::instance = nullptr;
                    std::mutex DatabaseConnectionPool::mutex_;

单例模式的招式解析

招式一:懒汉式(Lazy Initialization)
// 特点:需要时才创建实例,节省资源
// 缺点:需要处理多线程安全问题
招式二:饿汉式(Eager Initialization)
class EagerSingleton {
private:
static EagerSingleton instance;  // 类加载时就初始化
EagerSingleton() = default;
public:
static EagerSingleton& getInstance() {
return instance;  // 直接返回已创建的实例
}
};
// 静态成员定义
EagerSingleton EagerSingleton::instance;
招式三:Meyer’s Singleton(推荐)
// 利用C++11的局部静态变量线程安全特性
// 简洁、安全、自动销毁

完整测试代码

// 测试单例模式的各种实现
void testSingletonPattern() {
std::cout << "=== 单例模式测试开始 ===" << std::endl;
// 测试传统单例
Singleton* s1 = Singleton::getInstance();
Singleton* s2 = Singleton::getInstance();
std::cout << "传统单例地址比较: " << (s1 == s2 ? "相同" : "不同") << std::endl;
// 测试现代单例
ModernSingleton& ms1 = ModernSingleton::getInstance();
ModernSingleton& ms2 = ModernSingleton::getInstance();
std::cout << "现代单例地址比较: " << (&ms1 == &ms2 ? "相同" : "不同") << std::endl;
// 测试模板单例 - 配置管理器
ConfigurationManager& config1 = ConfigurationManager::getInstance();
ConfigurationManager& config2 = ConfigurationManager::getInstance();
config1.loadConfig("服务器配置数据");
std::cout << "配置数据: " << config2.getConfig() << std::endl;
std::cout << "配置管理器地址比较: " << (&config1 == &config2 ? "相同" : "不同") << std::endl;
// 测试日志系统
Logger::getInstance().info("应用程序启动");
Logger::getInstance().warn("内存使用率较高");
Logger::getInstance().error("数据库连接失败");
// 测试数据库连接池
DatabaseConnectionPool* pool = DatabaseConnectionPool::getInstance();
pool->acquireConnection();
pool->acquireConnection();
pool->releaseConnection();
std::cout << "=== 单例模式测试结束 ===" << std::endl;
}
int main() {
testSingletonPattern();
return 0;
}

单例模式的武学心得

适用场景
  • 资源共享:数据库连接池、线程池
  • 配置管理:应用程序配置信息
  • 日志系统:统一的日志记录
  • 设备管理器:打印机、文件系统等
优点
  • 严格控制实例数量:确保全局唯一性
  • 全局访问点:方便其他对象访问
  • 延迟初始化:需要时才创建,节省资源
缺点
  • 违反单一职责原则:同时承担创建和业务逻辑
  • 测试困难:难以模拟和测试
  • 隐藏依赖关系:全局状态可能带来意想不到的副作用

武林高手的点评

Factory Method 抚掌笑道:“Singleton 兄果然了得!你这’唯一存在’的武学理念,在需要严格控制实例数量的场景下确实无人能及。不过…” 他话锋一转,“过度使用可能导致代码耦合度增加,还需谨慎为之啊!”

Singleton 微微颔首:“道兄所言极是。我这武学虽强,却不可滥用。只有在真正需要全局唯一性的场景下,才该请我出手。”

下章预告

在Singleton展示完他那孤高的剑法后,Factory Method 缓步走出,他腰间工具碰撞的清脆声响吸引了所有人的注意。

“Singleton 兄的’唯一之道’确实精妙,但软件江湖中,更多时候我们需要的是’灵活创造’的能力。” Factory Method 微笑着说道,“下一章,我将为大家展示如何通过’工厂方法’来解耦对象的创建与使用,让我们的系统更加灵活、可扩展!”

架构老人满意地点头:“善!创造之道,变化万千。下一章,就请 Factory Method 展示他的创造艺术!”


欲知 Factory Method 如何通过工厂方法模式实现对象的灵活创建,且听下回分解!

posted on 2025-10-22 14:58  ycfenxi  阅读(0)  评论(0)    收藏  举报