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

单例的弊端

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

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

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

如:

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

单例的避免

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

怎么注入呢?通常可以通过对象的构造函数,或者 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
}
相关推荐
今天会营业4 天前
单例模式:饿汉和懒汉
单例模式
小小晓.5 天前
C++单例模式万字详解:6种实现演进+线程安全彻底解决+CRTP终极模板
c++·单例模式
软件黑马王子6 天前
3.单例模式问题1:构造函数
开发语言·单例模式·c#
软件黑马王子6 天前
4.单例模式问题2:重复挂载
开发语言·单例模式·c#
软件黑马王子6 天前
5.单例模式问题3:多线程问题
单例模式·前端框架·c#
旧梦95279 天前
Java 单例模式:从基础到实战的完整指南
java·开发语言·单例模式
码匠许师傅10 天前
【设计模式精讲】4.单例模式(Singleton)
c++·单例模式·设计模式
米啦啦.11 天前
设计模式/
观察者模式·单例模式·设计模式·工厂模式
布莱克60512 天前
单例模式详解:什么是单例模式,它能解决哪些问题?
开发语言·qt·单例模式
拓人间精准客12 天前
ToB 销售获客避坑指南:如何用全维度大数据实现降本增效
大数据·数据结构·单例模式