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

单例的弊端

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

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

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

如:

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

单例的避免

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

怎么注入呢?通常可以通过对象的构造函数,或者 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
}
相关推荐
yunn_4 小时前
单例模式两种实现方法
开发语言·c++·单例模式
I Promise341 天前
C++ 单例模式超详细讲解
开发语言·c++·单例模式
阿文的代码库2 天前
C++的单例模式及其作用
开发语言·c++·单例模式
Shan12052 天前
一文读懂:C++中单例模式的实现
java·c++·单例模式
老码观察2 天前
设计模式实战解读(一):单例模式——全局唯一实例的正确打开方式
单例模式·设计模式
mingshili2 天前
[Python] Python中自带模块级的单例模式-不需要定义单例类
python·单例模式
闪电麦坤952 天前
从第一性原理理解单例模式
单例模式
程序员榴莲3 天前
Python 单例模式
开发语言·python·单例模式
小江的记录本4 天前
【Java并发编程】锁机制:volatile:JMM内存模型、可见性/禁止指令重排、内存屏障、单例模式中的应用(附《思维导图》+《面试高频考点清单》)
java·后端·python·mysql·单例模式·面试·职场和发展