开发者

A Singleton that is not globally accessible

I just wondered what the best way is to get rid of the globally available static getInstance() in a Singleton. I do not want my Singleton classes being accessed from every point in my program.

I thought about maybe having a create() public static function that creates one object and returns it but one cannot call this method twice.

But it's not very elegant for me. Than I would have to make an assertion or throw an exception in case create() gets called a second time.

I开发者_如何学运维s there any other way I can achieve what I want?


You said that "creating one a second time would damage the whole application.". My response is: so don't make more then one. In C++, the type system is too weak to easily ensure this at compile-time. We can still write up a utility to approximate it at run-time, though.

Note, though, that this in no way implies you should use a singleton. (You have zero need for a global; it's unfortunate the drones have associated single-instance with global). What you want is this:

#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;

Now you get an exception if the class is constructed more than once:

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

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


Remove the Singleton and re-insert the enclosed function to where it should actually be, with appropriate access modifiers.

See here for a definitive list of reasons why singletons are an antipattern.

Especialy important - see here for the different between Singleton (the GoF pattern) and singleton (as in 'there is one and only one of me').


You could make your getInstance() method protected, and allow access via friend declarations. You'll have to manually "whitelist" classes with access to getInstance() both by adding a friend declaration.

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();
  }
};
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜