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

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

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

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

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

单例模式的武学精要

核心心法

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

C++ 代码实战
cpp 复制代码
#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

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

cpp 复制代码
#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)
cpp 复制代码
// 特点:需要时才创建实例,节省资源
// 缺点:需要处理多线程安全问题
招式二:饿汉式(Eager Initialization)
cpp 复制代码
class EagerSingleton {
private:
    static EagerSingleton instance;  // 类加载时就初始化
    
    EagerSingleton() = default;
    
public:
    static EagerSingleton& getInstance() {
        return instance;  // 直接返回已创建的实例
    }
};

// 静态成员定义
EagerSingleton EagerSingleton::instance;
招式三:Meyer's Singleton(推荐)
cpp 复制代码
// 利用C++11的局部静态变量线程安全特性
// 简洁、安全、自动销毁

完整测试代码

cpp 复制代码
// 测试单例模式的各种实现
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 如何通过工厂方法模式实现对象的灵活创建,且听下回分解!

相关推荐
huangyuchi.13 小时前
【Linux实战 】Linux 线程池的设计、实现与单例模式应用
linux·c++·单例模式·线程池·懒汉模式·项目·linux系统
拧之2 天前
✅设计模式笔记
笔记·单例模式·设计模式
蓝莓味的口香糖3 天前
【JS】什么是单例模式
开发语言·javascript·单例模式
稚辉君.MCA_P8_Java6 天前
DeepSeek Java 单例模式详解
java·spring boot·微服务·单例模式·kubernetes
坐不住的爱码7 天前
单例模式入门
单例模式
CoderIsArt7 天前
四种对象型创建模式:抽象工厂、 build模式、原型ProtoType与单例模式
单例模式·原型模式
charlie1145141919 天前
精读C++20设计模式——创造型设计模式:单例模式
c++·学习·单例模式·设计模式·c++20
Mr_WangAndy11 天前
C++设计模式_创建型模式_单件模式
c++·单例模式·设计模式
舒克起飞了11 天前
设计模式——单例模式
java·单例模式·设计模式