设计模式之单例模式

单例模式介绍

单例模式是最简单的设计模式之一。
有时我们只需要类的一个实例,例如多个对象共享的单个 DB 连接,因为为每个对象创建单独的 DB 连接可能成本很高。类似地,应用程序中可以有一个配置管理器或错误管理器来处理所有问题,而不是创建多个管理器。

定义:

单例模式是一种将类的实例化限制为一个对象的设计模式。

单例模式(单例类): 即该类只有一个实例化对象,不管外部声明调用多少次,其本质也都是访问同一块内存。

单例模式的核心是构造方法的私有化(即在入口处限制了对象的实例化),之后在类的内部实例化对象,并通过静态方法返回实例化对象的引用。

注意线程安全:
单例模式在多线程的 应用场合下必须小心使用。如果当唯一实例尚未创建时,有两个线程同时调用创建方法,那么它们同时没有检测到唯一实例的存在,从而同时各自创建了一个实例, 这样就有两个实例被构造出来,从而违反了单例模式中实例唯一的原则。 解决这个问题的办法是为指示类是否已经实例化的变量提供一个互斥锁(虽然这样会降低效率)。

代码实现:

在c++11之前,我们写单例模式的时候会遇到一个问题,就是多种类型的单例可能需要创建多个类型的单例,主要是因为创建单例对象的构造函数无法统一,各个类型的形参不尽相同。用模块可以解决。


#include <map>
#include <string>
#include <memory>
using namespace std;

template < typename T, typename K = string>
class Multiton
{
public:
    template<typename... Args>
    static std::shared_ptr<T> Instance(const K& key, Args&&... args)
    {
        return GetInstance(key, std::forward<Args>(args)...);
    }

    template<typename... Args>
    static std::shared_ptr<T> Instance(K&& key, Args&&... args)
    {
        return GetInstance(key, std::forward<Args>(args)...);
    }
private:
    template<typename Key, typename... Args>
    static std::shared_ptr<T> GetInstance(Key&& key, Args&&...args)
    {
        std::shared_ptr<T> instance = nullptr;
        auto it = m_map.find(key);
        if (it == m_map.end())
        {
            instance = std::make_shared<T>(std::forward<Args>(args)...);
            m_map.emplace(key, instance);
        }
        else
        {
            instance = it->second;
        }

        return instance;
    }

private:
    Multiton(void);
    virtual ~Multiton(void);
    Multiton(const Multiton&);
    Multiton& operator = (const Multiton&);
private:
    static map<K, std::shared_ptr<T>> m_map;
};

template <typename T, typename K>
map<K, std::shared_ptr<T>> Multiton<T, K>::m_map;

调用boost库写的一个单例类,包含工厂方法,线程安全

test1.h

template<typename T>
class First {
public:
	//单例模式,保证线程安全,返回工厂模式创建的对象
	static boost::shared_ptr<T> &ins() {
		if (NULL == pointer) {
			//lock_guard自动加锁解锁,构造函数里加锁,析构函数里解锁
			boost::lock_guard<boost::mutex> locker(s_mutex);
			if (NULL == pointer) {
				//make_shared自由工厂函数。可以接受最多10个参数,然后把它们传递给类型T的构造函数,创建一个shared_ptr<T>的对象并返回
				pointer = boost::make_shared<T>();
			}
		}
		return pointer;
	}

protected:
	//构造函数,设置为保护防止用户直接创建对象
	First() {};

protected:
	//单例模式程序唯一实例。shared_ptr智能指针
	static boost::shared_ptr<T> pointer;
	//保证线程安全。互斥锁
	static boost::mutex s_mutex;
};

template<typename T>
boost::shared_ptr<T> First<T>::pointer; //智能指针

template<typename T>
boost::mutex First<T>::s_mutex; //锁

上面创建了一个单例类,其它类可以继承这个单例类来创建对象。

#include <iostream>
using namespace std;
#include "test1.h"

//创建一个类继承单例类
class F3 :public First<F3> {
public:
	string st1() { cout << "ok"; };
};

int main() {

	//F3类也会是单例,调用F3类的方法。
	F3::ins()->st1();
	return 0;
}

单例模式一般和工厂模式一起使用

工厂模式:https://blog.csdn.net/a15322910600/article/details/120986282

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值