【单例模式】以C++实现Json串读写
1. 什么是单例模式
- 单例模式是指在内存中只会创建且仅创建一次对象的设计模式。
- 在程序中多次使用同一个对象且作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象。
- 单例模式在整个系统生命周期内,保证一个类只能产生一个实例,确保该类的唯一性。
2. 单例模式的作用:线程安全
- 给共享的资源加把锁,保证每个资源变量每时每刻至多被一个线程占用。
- 或者让线程也拥有资源,不用去共享进程中的资源。
3. 单例模式分类
1. 懒汉式
系统运行中,实例并不存在,只有当需要使用该实例时,才会去创建并使用实例。这种方式要考虑线程安全。
2. 饿汉式
系统一运行,就初始化创建实例,当需要时,直接调用即可。这种方式本身就线程安全,没有多线程的线程安全问题。
4. 单例类的特点
- 构造函数和析构函数为私有类型,目的是禁止外部构造和析构。
- 拷贝构造函数和赋值构造函数是私有类型,目的是禁止外部拷贝和赋值,确保实例的唯一性。
- 类中有一个获取实例的静态方法,可以全局访问。用户通过接口获取实例:使用 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);