一个不可全局访问的单例

时间:2010-10-13 17:57:06

标签: c++ design-patterns singleton

我只是想知道在Singleton中摆脱全局可用的静态getInstance()的最佳方法是什么。我不希望从我的程序中的每一点访问我的Singleton类。

我想过可能有一个create()公共静态函数,它创建一个对象并返回它,但是一个人不能两次调用这个方法。

但对我来说这不是很优雅。如果第二次调用create(),我将不得不进行断言或抛出异常。

有没有其他方法可以实现我的目标?

3 个答案:

答案 0 :(得分:3)

你说过“再次创建一个会损坏整个应用程序。”我的回答是:所以不要多做一个。在C ++中,类型系统太弱,无法在编译时轻松确保这一点。不过,我们仍然可以在运行时编写一个实用程序来近似它。

但请注意,这绝不意味着您应该使用单身人士。 (你不需要全局;不幸的是无人机将单实例与全局相关联)。你想要的是这个:

#include <stdexcept>

// inherit from this class (privately) to ensure only
// a single instance of the derived class is created
template <typename D> // CRTP (to give each instantiation its own flag)
class single_instance
{
protected: // protected constructors to ensure this is used as a mixin
    single_instance()
    {
        if (mConstructed)
            throw std::runtime_error("already created");

        mConstructed = true;
    }

    ~single_instance()
    {
        mConstructed = false;
    }

private:
    // private and not defined in order to
    // force the derived class be noncopyable
    single_instance(const single_instance&);
    single_instance& operator=(const single_instance&);

    static bool mConstructed;
};

template <typename T>
bool single_instance<T>::mConstructed = false;

现在,如果类被构造多次,则会出现异常:

class my_class : private single_instance<my_class>
{
public:
    // usual interface (nonycopyable)
};

int main()
{
    my_class a; // okay
    my_class b; // exception
}

答案 1 :(得分:2)

删除Singleton并使用适当的访问修饰符将附带的函数重新插入到它实际应该的位置。

请参阅此处查看a definitive list of reasons why singletons are an antipattern

特别重要 - 请参阅here了解Singleton(GoF模式)和单身人士之间的不同之处(如“我只有一​​个人”)。

答案 2 :(得分:1)

您可以对getInstance()方法进行保护,并允许通过friend声明进行访问。您必须通过添加getInstance()声明来手动“列入”可以访问friend的类的白名单。

class Singleton {
protected:
  static Singleton* getInstance() { return Singleton::s_instance_; }
  // Allow access to SingletonUser
  friend class SingletonUser;
private:
  Singleton() { }
  static Singleton* s_instance_;
};

class SingletonUser {
public:
  void doStuff() {
    // Fails if not a friend of Singleton
    Singleton* s = Singleton::getInstance();
  }
};
相关问题