C++ Singleton/Active Object Paradigm

2019-08-20 19:42发布

问题:

I was wondering how you would make a class where you create several instances i.e

Session o1 = new Session();
Session o2 = new Session();

You could then make these sessions the active session like so.

o1.makeActiveSession();
Session::setActiveSession(o2);

Then at any point in my code I could go:

Session::getActiveSession();

and it would return the active session object or create new one if one doesn't exist. Only one session can be the active session at any one time, so if a session is told to become the active session then the old one is deactivated.

So my question is, how would I make something like this ?

回答1:

You should be able to take most any of the common Singleton implementations, and modify it to be a manager with CreateNew() and SetActive() functions available.

// Session.h
class ActiveSessionManager;
class Session
{
public:

protected:
  Session(){};

  void MakeActiveSession();

  friend class ActiveSessionManager;
};

// ActiveSessionManager.h
class ActiveSessionManager
{
public:
  static Session *GetActiveSession()
  {
    if ( s_active == nullptr )
    {
      s_active = new Session();
    }

    return s_active;
  }

  static void SetActiveSession( Session *session )
  {
    s_active = session; 
  }

  static Session *CreateNewSession()
  {
    return new Session();
  }

  static Session *CreateNewActiveSession()
  {
    s_active = CreateNewSession();
    return s_active;
  }

private:
  ActiveSessionManager(){};

  static Session *s_active;
};

// I would put these in cpps.
Session *ActiveSessionManager::s_active = nullptr;

void Session::MakeActiveSession()
{
  ActiveSessionManager::SetActiveSession( this );
}

In my implementation I only allow ActiveSessionManager to instance Sessions, as it would then be able to keep track of all sessions generated ( the tracking is left as an exercise for the reader ).

You could combine the manager and session into a single class as well, but I find the separation easier to follow.



回答2:

This is lazy-loading based singleton:

class Session
{
public:
    static Session& getInstance() {
        static Session s;                   // <-- instantiated upon first call
        return s;
    }

private:
    Session() { }                           // <-- private constructor
    ~Session() { }
    Session(const Session&);                // <-- private copy constructor
    Session& operator=(const Session&);     // <-- private assignment operator
};

used as:

Session& s = Session::getInstance();