SINGLETON(单例)—— 对象创建型模式

SINGLETON(单例)—— 对象创建型模式

概述:保证一个类只有一个实例,并且提供一个访问它的全局访问点。

关键对象:Singleton

  • 定义一个GetInstance操作,保证只有在第一次调用是才会生成Singleton对象,以后的调用返回的是唯一已经存在的实例;
  • 为了防止在外部对Singleton类实例化,它的构造函数被设为private;
  • 在Singleton类的内部定义了一个Singleton类型的静态对象,作为提供外部共享的唯一实例。

交互方式:只能用过Singleton的GetInstance操作访问它唯一的一个Singleton实例。
适用场景:

  • 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它。
  • 当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需要改代码就能使用一个扩展的实例。

结构图示:
在这里插入图片描述
优缺点:

  • 对唯一实例的受控访问:因为Singleton类封装它的唯一实例,所以它可以严格的控制怎样以及何时访问它;
  • 缩小名空间:Singleton模式是对全局变量的一种改进。它避免了那些存储唯一实例的变量污染名空间;
  • 允许对操作和表示的精化:Singleton类可以有子类,而且用这个扩展类的实例来配置应用是很容易的。可以用所需要的类的实例在运行时刻配置应用;
  • 允许可变数目的实例:这个模式使得你易于改变你的想法,并允许Singleton类的多个实例。此外,你可以用相同的方法来控制应用所使用的实例的数目。只有允许访问Singleton实例的操作需要改变;
  • 比类操作更灵活:另一种封装单件功能的方式是使用类操作。但这两种语言技术都难以改变设计以允许一个类有多个实例。此外,C++中的静态成员函数不会虚函数,因此子类不能多态的重定义它们。
  • 单例模式中没有抽象层,因此单例类的扩展有困难;
  • 单例类的职责过重,在一定程度上违背了单一职责的原则。因为单例类即提供了业务方法,又提供了创建对象的方法,将对象的创建和对象本身的功能耦合在一起。
  • 很多高级面向对象编程语言如C#和Java等都提供了垃圾回收机制,如果实例化的共享对象长时间不被利用,系统则会认为它是垃圾,于是会自动销毁并回收资源,下次利用时又得重新实例化,这将导致共享的单例对象状态的丢失。

简单示例:

file: Config.h

#ifndef _CONFIG_H_
#define _CONFIG_H_
#include <string>

class Config
{
    public:
        ~Config();
        static Config *GetInstance();
        bool Load(std::string path="./config.json");
        void Writejsonfile();
        std::string Json();
    protected:
        template <typename PrettyWriter>
        void serialize(PrettyWriter &writer) const;
    public:
        std::string m_path;
        std::string m_version;
        int m_width;
        int m_height;
    private:
        Config();
        static Config *_instance;
};

#endif

file: Config.cpp

#include <fstream>
#include <rapidjson/document.h>
#include <rapidjson/prettywriter.h>
#include <iostream>
#include "config.h"

using namespace std;
using namespace rapidjson;

Config *Config::_instance = 0;
Config *Config::GetInstance() {
    if(!_instance) {
        _instance = new Config();
    }
    return _instance;
}

Config::Config() {
    load();
}

Config::~Config() {
    if(_instance) {
        delete _instance;
        _instance = NULL;
    }
}

void Config::writejsonfile() {
    std::string jsondata;
    long size;
    jsondata = json();
    ofstream file(m_path, ios::out|ios::binary|ios::trunc);
    size = jsondata.size();
    file.write(jsondata.c_str(),size);
    file.close();
}

std::string readjsonfile(const char* jsonfile) {
    std::ifstream fin;
    std::string jsondata = " ";
    fin.open(jsonfile,std::ifstream::in);
    if (!fin.is_open()) {
        cout << "--- read json file error." << endl;
    }
    std::string line;
    while(getline(fin,line)) {
        jsondata.append(line + "\n");
    }
    return jsondata;
}

bool Config::load(std::string path) {
    std::string json = readjsonfile((char *)path.c_str());
    m_path = path;
    Document doc;
    doc.Parse(json.c_str());
    if (doc.IsObject()) {
        if (doc.HasMember("version")) {
            if (doc["version"].IsString()) {
                version = doc["version"].GetString();
            }
        }
        if (doc.HasMember("width")) {
            if(doc["width"].IsUint()) {
                width = doc["width"].GetUint();
            }
        }
        if (doc.HasMember("height")) {
            if (doc["height"].IsUint()) {
                height = doc["height"].GetUint();
            }
        }
    } else {
        cout << "---There is nonstandard jsondata." << endl;
    }
    return true;
}

template <typename PrettyWriter>
void Config::serialize(PrettyWriter &writer) const {
    writer.StartObject();
    writer.Key("version");
    writer.String(m_version.c_str());
    writer.String("width");
    writer.Uint(m_width);
    writer.String("height");
    writer.Uint(m_height);
    writer.EndObject();	
}

std::string Config::json() {
    StringBuffer sb;
    PrettyWriter<StringBuffer> writer(sb);
    serialize(writer);
    return sb.GetString();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值