【单例模式】以C++实现Json串读写

1. 什么是单例模式

  • 单例模式是指在内存中只会创建且仅创建一次对象的设计模式。
  • 在程序中多次使用同一个对象且作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象。
  • 单例模式在整个系统生命周期内,保证一个类只能产生一个实例,确保该类的唯一性。

2. 单例模式的作用:线程安全

  • 给共享的资源加把锁,保证每个资源变量每时每刻至多被一个线程占用。
  • 或者让线程也拥有资源,不用去共享进程中的资源。

3. 单例模式分类

1. 懒汉式

系统运行中,实例并不存在,只有当需要使用该实例时,才会去创建并使用实例。这种方式要考虑线程安全。
2. 饿汉式
系统一运行,就初始化创建实例,当需要时,直接调用即可。这种方式本身就线程安全,没有多线程的线程安全问题。

4. 单例类的特点

  1. 构造函数和析构函数为私有类型,目的是禁止外部构造和析构。
  2. 拷贝构造函数和赋值构造函数是私有类型,目的是禁止外部拷贝和赋值,确保实例的唯一性。
  3. 类中有一个获取实例的静态方法,可以全局访问。用户通过接口获取实例:使用 static 类成员函数。

5. 我使用的局部变量懒汉单例式

class JsonConfig
{
public:
	static JsonConfig &instance();
    
private:

	JsonConfig(){};
    ~JsonConfig(){};

    JsonConfig(const JsonConfig &signal);
    const JsonConfig &operator=(const JsonConfig &signal);
}

JsonConfig & JsonConfig::instance()
{
    /**
     * 局部静态特性的方式实现单实例。
     * 静态局部变量只在当前函数内有效,其他函数无法访问。
     * 静态局部变量只在第一次被调用的时候初始化,也存储在静态存储区,生命周期从第一次被初始化起至程序结束止。
     */
    static JsonConfig m_instance;
    return m_instance;
}

6. C++实现

config.h

#ifndef CONFIG_H
#define CONFIG_H

#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

class JsonConfig
{
public:
	static JsonConfig &instance();

	template <typename T>
	T get(const std::string &name)
	{
		try
		{
			loadPt();
			return m_pt.get<T>(name);
		}
		catch (boost::property_tree::ptree_bad_path const &e)
		{
			std::cout << e.what() << std::endl;
			throw;
		}
		catch (std::exception const &e)
		{
			std::cout << "unexpected error, " << e.what() << std::endl;
			throw;
		}
	};

	template <typename T>
	std::vector<T> getVector(const std::string &name)
	{
		try
		{
			std::vector<T> value{};
			
			loadPt();
			for (const auto &itr : m_pt.get_child(name))
			{
				value.emplace_back(itr.second.get_value<T>());
			}
			return value;
		}
		catch (boost::property_tree::ptree_bad_path const &e)
		{
			std::cout << e.what() << std::endl;
			throw;
		}
		catch (std::exception const &e)
		{
			std::cout << "unexpected error, " << e.what() << std::endl;
			throw;
		}
	};

	template <typename T>
	bool add(const std::string &key,const T &value)
	{
		try
		{
			m_pt.add(key, value);//put and add
			boost::property_tree::write_json(m_sJsonPath, m_pt);

			return true;
		}
		catch(const std::exception& e)
		{
			std::cout << e.what() << '\n';
		}
		
	}

	template <typename T>
	bool addVector(const std::string &key,const std::vector<T> &value)
	{
		try
		{
			boost::property_tree::ptree childs;
			for (int i = 0 ;i<value.size();i++)
			{
				T result = value[i]; 
				boost::property_tree::ptree child1;
				child1.put("",result);
				childs.push_back(std::make_pair("", child1));
			}

			m_pt.put_child(key, childs);
			boost::property_tree::write_json(m_sJsonPath, m_pt);
			return true;
		}
		catch(const std::exception& e)
		{
			std::cout << e.what() << '\n';
		}
	}

	template <typename T>
	bool change(const std::string &key, const T &value)
	{
		try
		{
			m_pt.get_child(key).put_value(value);
			boost::property_tree::write_json(m_sJsonPath, m_pt);
			return true;
		}
		catch(const std::exception& e)
		{
			std::cout << e.what() << '\n';
		}	 
	}

	template <typename T>
	bool changeVector(const std::string &key, const std::vector<T> &value)
	{
		try
		{
			addVector(key,value);
			return true;
		}
		catch(const std::exception& e)
		{
			std::cout << e.what() << '\n';
		}
	}

	//template <typename T>
	bool check(const std::string &name);//,T &result)


	template <typename T>
	bool checkVector(const std::string &name,std::vector<T> &result)
	{
		try
		{
			loadPt();
			for (const auto &itr : m_pt.get_child(name))
			{
				result.emplace_back(itr.second.get_value<T>());
			}
			return true;
		}
		catch (boost::property_tree::ptree_bad_path const &e)
		{
			std::cout << e.what() << std::endl;
			return false;
		}
		catch (std::exception const &e)
		{
			std::cout << "unexpected error, " << e.what() << std::endl;
			return false;
		}
		return true;
	};

	bool set(const auto &value,const std::string &key="");
	bool erase(const std::string &key);
	bool show();
	bool clear();

	bool setJsonPath(const std::string &path);
    std::string getJsonPath(){return m_sJsonPath;};

private:
    bool loadPt();
    std::string m_sJsonPath;
	boost::property_tree::ptree m_pt;

	JsonConfig(){};
    ~JsonConfig(){};

    // 将其拷贝构造和赋值构造成为私有函数, 禁止外部拷贝和赋值
    JsonConfig(const JsonConfig &signal);
    const JsonConfig &operator=(const JsonConfig &signal);

};

#endif

config.cpp

#include "config.h"  
    
using namespace std;  
using namespace boost::property_tree;

bool JsonConfig::loadPt()
{
    if(m_sJsonPath.length() != 0)
    {
        read_json(m_sJsonPath, m_pt);
    }
    else
    {
        cout << "invaild json path .. " << endl;
        return false;
    }

    return true;
}

bool JsonConfig::setJsonPath(const string &path)
{
    if(path.length() != 0)
    {
        m_sJsonPath = path;
        loadPt();
    }
    else
    {
        cout << "invaild json path .. " << endl;
        return false;
    }

    return true;
}

JsonConfig & JsonConfig::instance()
{
    /**
     * 局部静态特性的方式实现单实例。
     * 静态局部变量只在当前函数内有效,其他函数无法访问。
     * 静态局部变量只在第一次被调用的时候初始化,也存储在静态存储区,生命周期从第一次被初始化起至程序结束止。
     */
    static JsonConfig m_instance;
    return m_instance;
}

bool JsonConfig::set(const auto &value,const string &key)
{
    try
    {
        ptree m_child;
        ptree m_childs;
        m_child.put(key,value);
        m_childs.push_back(make_pair("", m_child));
        m_pt.push_back(make_pair("list", m_childs));
        return true;
    }
    catch(const exception& e)
    {
        cout << e.what() << '\n';
    }
}

bool JsonConfig::erase(const string &key)
{
    try
    {
        m_pt.erase(key);
        write_json(m_sJsonPath, m_pt);
        return true;
    }
    catch(const exception& e)
    {
        cout << e.what() << '\n';
    }			
}

bool JsonConfig::show()
{
    try
    {
        stringstream ss;
        write_json(ss, m_pt, true);
        string strContent = ss.str(); 
        cout << strContent << std::endl;
    }
    catch(const exception& e)
    {
        cout << e.what() << endl;
    }
}

bool JsonConfig::clear()
{
    try
    {
        m_pt.clear();
        return true;
    }
    catch(const std::exception& e)
    {
        cout << e.what() << '\n';
    }
}

bool JsonConfig::check(const std::string &name)
{
    try
    {
        loadPt();
        if(!m_pt.get_child_optional(name))
        {
            return false;
        }
        return true;
    }
    catch (boost::property_tree::ptree_bad_path const &e)
    {
        std::cout << e.what() << std::endl;
        return false;
    }
    catch (std::exception const &e)
    {
        std::cout << "unexpected error, " << e.what() << std::endl;
        return false;
    }
    return true;
}
// ptree参考用法:
// pt::tree root;
// pt::ptree child1, child2,child3, child4;
// pt::ptree childs;
// //单独一个数值
// child1.put("", 2);
// //单独一个字符串
// child2.put("", "asdh");
// //对象
// child3.put("key0", "val0");
// //构造数组,主意childs必须只有key为""的,不能有其他。不然会退化为对象
// //把数值加入数组
// childs.push_back(make_pair("", child1));
// childs.push_back(make_pair("", child2));
// childs.push_back(make_pair("", child3));
// childs.push_back(make_pair("", childs));
// //键为list,值为childs数组
// root.put("list", childs);
  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值