说单例就要把初始化参数写死到类里面。那么我们来举一个例子。

比如我们有一个INI读写类,因为读写同一个文件,那做成单例肯定有好处,不会多个实例访问。代码如下:

class Config : public QObject{
public:
    // 单实例
    static Config& i();
 
    void save(const QString &key,const QVariant &value);
};
// 基本没问题,单例就用上面的方法创建:
Config &Config::i(){
    static Config cfg();
 
    return cfg;
}
Config::Config() : QObject(nullptr){
    m_configFile0 = new QSettings("c:\\abc.ini",QSettings::IniFormat);
 
    // 解决中文乱码问题
    m_configFile0->setIniCodec(QTextCodec::codecForName("UTF-8"));
}

看到没,这个扛精他把文件写到构造函数类里面,文件为c:\\abc.ini。

也就是说,他这个Config类,移植到别的工程的时候,都要改一下这个文件名,才能起一个新名字。当然他也可以起一个唯一的跟程序绑定名字,目录也可以放到temp,这又是牛角尖,我们不说。

假如他是负责这个模块,然后这个模块,比如dll,要给别的exe工程用,那是不是每个exe都要一个不同的dll?他还没发现他在做重复工作是不是?svn一大堆重复的Config工程?

那我们变通下:

class Config : public QObject{
public:
    // 单实例,增加参数
    static Config& i(QString file="");
 
    void save(const QString &key,const QVariant &value);
};

Config &Config::i(QString file){
    static Config cfg(file);
 
    return cfg;
}
// 构造时增加参数
Config::Config(QString file) : QObject(nullptr){
    m_configFile0 = new QSettings(file,QSettings::IniFormat);
 
    // 解决中文乱码问题
    m_configFile0->setIniCodec(QTextCodec::codecForName("UTF-8"));
}

如上所述,这个dll首次构造时是可以带一个参数进去的,就是可以把配置文件路径传进去,后续访问是不需要的。

这样,这个dll只需要维护一份,就可以配形形色色的exe了。