浅谈:单例模式的弊端与对策

单例的弊端

回顾以下单例模式的定义:保证一个类仅有一个实例,并提供一个该实例的全局访问点。

这里提到了「 **全局 」**两个字,可见单例本质就是一种全局资源。

那自然无法避免全局对象的各种弊端;

如:

  • 滥用问题,任何人都可以使用该资源
  • 生命周期问题,该对象从构造起贯穿整个应用程序种
  • 缺乏灵活性,全局资源的修改将涉及直接使用和间接使用的全部模块
  • 测试的困难,使用全局资源点不方便进行单元测试

单例的避免

其实解决的方法有不少,这里展示注入的方式对取消单例。

怎么注入呢?通常可以通过对象的构造函数,或者 set 方法将原先的单例对象注入到目标对象中。

单例的方式

复制代码
class MySql {
public:
    static MySql& instance() {
        static MySql s_instance;
        return s_instance;
    }

public:
    void foo() {}

private:
    MySql() = default;
    ~MySql() = default;

private:
    MySql(const MySql&) = delete;
    MySql& operator=(const MySql&) = delete;
};

// 依赖于单例
class Widget {
private:
    MySql* sql;

public:
    Widget() {
        sql = &MySql::instance();
    }

    void refresh() {
        sql->foo();
        // TODO
    }
};

int main() {
    Widget widget;
    widget.refresh();
    // TODO
}

注入的方式

复制代码
class MySql {
public:
    MySql() = default;
    ~MySql() = default;

public:
    void foo() {}
};

// 完全独立的模块
class Widget {
private:
    MySql* sql;

public:
    Widget(MySql* sql) : sql(sql) {
    }

    void refresh() {
        sql->foo();
        // TODO
    }
};

int main() {
    MySql sql;
 
    // 通过构造器进行注入
    Widget widget(&sql);
    widget.refresh();
    // TODO
}
相关推荐
captain37611 小时前
多线程单例模式
java·单例模式·java-ee
2301_777998345 天前
C++ 单例模式详解:饿汉、懒汉,以及“对象”和“对象指针”到底有什么区别
开发语言·c++·单例模式
breeze jiang8 天前
JavaScript 单例模式:用静态属性保证 Popup 只创建一次
开发语言·javascript·单例模式
meilindehuzi_a8 天前
WebGPU DeepSeek项目实战(二):用单例模式加载Tokenizer并转发下载进度
单例模式·typescript·react
啦啦啦啦啦zzzz17 天前
设计模式:单例模式和工厂模式
c++·单例模式·设计模式·工厂模式
空杆推不起18 天前
金融数仓标准化:信贷业务 ODS/DWD/DWS/ADS/DIM 全层级建模指南
单例模式·金融
芝士熊爱编程25 天前
创建型模式-单例模式
java·单例模式·设计模式
张小姐的猫1 个月前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
zjun10011 个月前
C++:单例模式
c++·单例模式
ttod_qzstudio1 个月前
【软考设计模式】单例模式:唯一实例的管控与线程安全精讲
单例模式·设计模式