一、介绍:
编写一个单例框架,使得最终通过一行宏定义,将一个类变为单例类。减少客户侧定义单例类时编写重复代码。
二、代码:
2.1、单例框架代码:
// Singleton.h
// description: 单例框架模板
// author: XXX
// date: XXX
#ifndef INCLUDE_TOOLS_SINGLETON
#define INCLUDE_TOOLS_SINGLETON
#include <iostream>
#include <atomic>
#include <utility>
template<typename class_name>
class Singleton
{
public:
using singleton_ptr = class_name*;
public:
template <typename... Args>
static singleton_ptr get_instance(Args &&... args)
{
if (!get_instance_ptr().load()) { // 判断是否第一次调用
get_instance_ptr().exchange(new class_name(std::forward<Args>(args)...));
std::cout << "create this class " << get_instance_ptr().load() << std::endl;
}
std::cout << "already created this class " << get_instance_ptr().load() << std::endl;
return get_instance_ptr().load();
}
static void destory()
{
auto ptr = get_instance_ptr().exchange(nullptr);
delete ptr;
}
private:
static std::atomic<singleton_ptr>& get_instance_ptr()
{
static std::atomic<singleton_ptr> instance_;
return instance_;
}
Singleton() = delete;
~Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
};
#define SINGLETON_CLASS(class_name) \
public: \
friend class Singleton<class_name>; \
template <typename... Args> \
static class_name* get_instance(Args &&... args) \
{ \
return Singleton<class_name>::get_instance(std::forward<Args>(args)...); \
} \
static void destory() \
{ \
Singleton<class_name>::destory(); \
}
#endif
2.2、客户侧使用代码:
// 客户侧使用代码
#include "Singleton.h"
// 单例测试类A
class A
{
SINGLETON_CLASS(A);
public:
void print_a_b() { std::cout << a << b << std::endl;}
private:
A(int x, int y) : a(x), b(y) {}
private:
int a;
int b;
};
// 单例测试类B
class B
{
SINGLETON_CLASS(B);
public:
void print_empty() { std::cout << "empty"<< std::endl;}
private:
B() = default;
};
2.3、使用案例:
void test_singleton()
{
A::get_instance(2, 3)->print_a_b();
std::cout << "--------Split line-------------" << std::endl;
B::get_instance()->print_empty();
A::get_instance(2, 3)->print_a_b();
}
源码链接: github地址
三、总结:
1、将目标类声明为单例时,在类声明中加入SINGLETON_CLASS(class_name);
即可。
2、使用目标单例时,调用class_name::get_instance()->
即可。