C++设计模式:单例模式-提供线程安全的单例模板类

//!
//! C++设计模式: 单例模式-提供线程安全的单例模板类
//!
//! == 单例模式简介 ==
//! 单例模式出现的原因是一个类在整个程序运行时,最多只能存在一个对象,
//!     单例类本身会构造出唯一的对象,并返回指针给使用者,
//!     为了防止使用者自己构造对象,单例类需要将构造函数限制在私有区域
//! 单例类的特性是一个程序只存在一个对象,且可以跨文件提供给使用者,
//!     这意味着单例类与全局变量一样,没有作用域的限制
//! == 单例模式简介 ==
//!
//!
//! == 单例类特点 ==
//! 单例类存在静态创建与动态创建两种方式:
//!     静态创建:在main函数执行前创建,在main函数结束后释放,无论是否使用都会创建对象
//!     动态创建:首次使用时创建,可以手动释放资源,不使用则不创建
//! 动态创建由于创建实际延时到调用时机,会出现多线程问题,需要线程同步,
//!     实际使用默认推荐静态创建,因为如果不使用该单例对象的话,就不应该存在这个文件
//! 如果存在多选一判断的单例类,即多个单例类中最后使用的结果未知,且只使用其中一个,
//!     推荐动态创建,以节约全局资源
//!
//! 单例模板类在使用上分为真单例与伪单例两种用法:
//!     真单例:构造函数私有,外部无法在创建新的对象
//!     伪单例:使用默认构造函数,提供单例对象接口,但外部可以创建对象
//! 当使用者不是自己是,往往需要提供真单例给其他人使用,以防止误操作,
//!     但如果创建与使用单例的但是自己,则推荐伪单例,因为明确知道类的使用方法,
//!     则不强制限制构造函数,非单例但当作单例使用,以达到快速开发的目的
//! == 单例类特点 ==
//!
//!
//! == 应用场景 ==
//! 单例类的唯一对象特性非常适合用于对资源对接,如存在唯一数据库,
//!     或者唯一日志类时的接口封装,且由于没有作用域的限制,
//!     使得被单例类控制的资源可以在全范围使用
//! 单例类无限制作用域的特点是一把双刃剑,即十分灵活也打破了模块封装的壁垒,
//!     如资源需要限制范围时,需谨慎使用单例模式
//! == 应用场景 ==
//!
//! 结束语:
//!     文章在最后提供Tsingle.h文件的单例模板,可供快速建立类,
//!         文章的测试代码直接运行,会导致打印内容混乱,
//!         最后的测试结果已经归纳好了单个test函数的输出结果
//!
#include "Tsingle.h"
#include 
#include 
#include 
#include 

using namespace std;

//===== 单例模式写法 =====
//== 静态创建 ==
//new singleton_s 的静态指针会在进入main函数之前执行,
//      exit_class 类的静态对象的析构函数会在main函数执行结束之后调用,
//      利用exit_class析构函数释放singleton_s指针内配的内存
class singleton_s
{
public:
    static singleton_s* get() { return _obj; }

    void print(string log)
    {
        cout<print("<< print singleton_s >>");
}

//动态创建与销毁时机测试
void test_2()
{
    cout<<"== test_2 =="<print("<< print singleton_d >>");
    singleton_d::get()->clear();
}

//===== 测试准备 =====
//静态模板: 限制构造函数--真单例
class vclog : public Tsingle_s
{
    TSINGLE(vclog,Tsingle_s)
public:
    void print(string log)
    {
        cout<<"vclog: "<
{
    TSINGLE(dclog,Tsingle_d)
public:
    void print(string log)
    {
        cout<<"dclog: "<print("123");             //真单例推荐用法
    Tsingle_s::get()->print("456");  //伪单例推荐用法

    //动态模板
    dclog::get()->print("123qwe");             //真单例推荐用法
    Tsingle_s::get()->print("456qwe");  //伪单例推荐用法
}


//===== 简单日志-单例 =====
#define cl ""<
    vlog& operator<<(const T &txt)
    { if(okc) std::cout< vec;
    std::string v_filename;

    std::string get_time()
    {
        time_t t; time(&t); char tmp[32];
        strftime(tmp,sizeof(tmp),"%Y-%m-%d %H:%M:%S",localtime(&t));
        return tmp;
    }
    class mcv { ~mcv(){delete obj; obj = nullptr;} }; static mcv t;
};
vlog* vlog::obj = nullptr;

#define vloge(...) \
    (*Tsingle_s::get())<] <<<< "<<__VA_ARGS__<::get())<] <<<< "<<__VA_ARGS__<::get())<] <<<< "<<__VA_ARGS__<::get())<] <<<< "<<__VA_ARGS__<::get()->init(vlog::e_debug); //设置打印等级

    //原生接口
    (*Tsingle_s::get())<::get())<::get())<::get())<>
== end ==
out singleton_s
out exit_class


 *
 * 2.动态创建与销毁时机测试
 *
== begin ==
== test_2 ==
in exit_class
in singleton_d
<< print singleton_d >>
out singleton_d
== end ==


 *
 * 3.模板单例模式测试
 *
== begin ==
== test_3 ==
vclog: 123
cclog: 456
dclog: 123qwe
dclog: 456qwe
== end ==


 *
 * 4.简单日志模板测试
 *
== begin ==
== test_4 ==
[Deb] 456
[War] qwe
[Err] asd
[Deb] [../cpp_design/singleton.cpp:<304>] <<<< 200
[War] [../cpp_design/singleton.cpp:<305>] <<<< 300
[Err] [../cpp_design/singleton.cpp:<306>] <<<< 400
== end ==

*/

//!
//! Tsingle.h
//!
#ifndef TSINGLE_H
#define TSINGLE_H

#include 

//单例模板限制宏
#define TSINGLE(class,single)           \
    public:                             \
    friend single;               \
    class() = default;                  \
    ~class() = default;                 \
    class(const class &) = delete;      \
    private:

//静态模板
template
class Tsingle_s
{
public:
    static T* get(){ return _obj; }

private:
    static T *_obj;
    friend T;
    Tsingle_s() { static exit_class exit; }
    ~Tsingle_s() = default;
    Tsingle_s(const Tsingle_s &) = delete ;

    struct exit_class { ~exit_class() { delete _obj; } };
};

//注意头文件的多重定义
template T *Tsingle_s::_obj = new T;

//动态模板
template
class Tsingle_d
{
public:
    static T* get()
    {
        if(_obj == nullptr)
        {
            _mut.lock();
            if(_obj == nullptr)
            { _obj = new T; }
            _mut.unlock();
        }
        return _obj;
    }

    void clean()
    {
        _mut.lock();
        delete _obj;
        _obj = nullptr;
        _mut.unlock();
    }

private:
    static T *_obj;
    static std::mutex _mut;
    friend T;
    Tsingle_d() = default;
    ~Tsingle_d() = default;
    Tsingle_d(const Tsingle_d &) = delete ;
};

//注意头文件的多重定义
template T *Tsingle_d::_obj = nullptr;
template std::mutex Tsingle_d::_mut;

#endif // TSINGLE_H

你可能感兴趣的:(单例模式,c++)