C ++ Singleton дизайн вопрос - PullRequest
4 голосов
/ 26 августа 2010

У меня есть требование иметь только один экземпляр класса в любой данный момент времени. Синглтон - очевидный кандидат. Но у меня есть некоторые другие условия, которые не типичны для синглтона.

  1. Время жизни синглтона не является временем жизни программы. Этот объект должен создаваться каждый раз, когда я вхожу в определенное состояние, и уничтожаться, когда я покидаю это состояние. На протяжении всей продолжительности состояния я не могу создать еще один экземпляр класса.
  2. Каждый раз, когда я вхожу в состояние и создаю новый экземпляр, мне нужно передать переменную в синглтон. Это число, основанное на выборе пользователя.

Итак, моя реализация имеет следующие статические функции -

// To be called exactly once, everytime I enter the state
void MySingleton::CreateInstance(size_t count);

// To be called any no. of times during the state
MySingleton * MySingleton::GetInstance();   

// To be called exactly once, when leaving the state.
void MySingleton::DestroyInstance();        

Теперь эта реализация является основным отклонением от обычной реализации синглтона.

Есть ли проблемы с такой реализацией?

Есть ли лучшие альтернативы?

Ответы [ 6 ]

12 голосов
/ 26 августа 2010

Если вы создаете экземпляр каждый раз, когда входите в данное состояние, и уничтожаете его каждый раз, когда выходите из этого состояния, было бы более разумно, чтобы экземпляр принадлежал тому, кто управляет переходами состояний (или какой-либо другой сущности, которая знает,переходов между штатами).

Например, вы можете иметь умный указатель на экземпляр в качестве переменной-члена менеджера состояний.Когда вы переходите в состояние, вы можете инициализировать его для нового экземпляра, а когда вы переходите из состояния, вы можете уничтожить этот экземпляр.

На мой взгляд, это будет чище и предпочтительнее, чем использование одиночного дизайна(анти) картины.

5 голосов
/ 26 августа 2010

Есть ли проблемы с такой реализацией?

Да. Проблема в том, что это не синглтон , потому что это не то, что означает "синглтон" . Это простая переменная, локальная для того состояния, в которое вы входите и выходите.

На самом деле синглтоны - это просто прославленные глобалы, живые на протяжении всего жизненного цикла приложения, и в любом случае их следует по возможности предотвращать. Ваш "Синглтон" не глобальный, а местный.

2 голосов
/ 26 августа 2010

Концепция, которую вы описываете, может быть обеспечена таким классом:

template<class Guarded>
class single_instance : private boost::noncopyable {
   static bool alive;
public:
   single_instance() {
      if (alive)
         throw std::runtime_error("instance already exists");
      alive = true;
   }
   ~single_instance() {
      alive = false;
   }
};

template<class Guarded>
bool single_instance<Guarded>::alive = false;

Если вы унаследуете свой класс от этого, будет гарантировано, что вы всегда можете создать только один экземпляр за раз:

class myclass : single_instance<myclass> {
public:
   myclass(size_t count);
   ...
};

Теперь вы можете реализовать и создать экземпляр myclass как обычный класс, без необходимости использования фабричных функций и getInstance методов. Попытка создания экземпляра второй копии до ее уничтожения приведет к исключению.

1 голос
/ 27 августа 2010

Я полностью согласен с «Синглтон - просто еще одна глобальная форма», и этого следует избегать.

Если ваш начальник настаивает, вы можете попробовать что-то вроде этого:

class MyUtil
{
    protected:
    static MyUtil* m_Singleton = NULL;
    public:
    /// Create the singleton if does not exist.
    /// \return the singleton for this class.
    static GetSingleton()
    {
        if( !m_Singleton  )
        m_Singleton  = new MyUtil();
        return m_Singleton ;
    }

    /// release singleton instance
    /// Warning: Multi-threading not supported.
    void StateRelease()
    {
        m_Singleton  = NULL;
        delete this;
    }
};
1 голос
/ 26 августа 2010

Если это по одному на состояние, то сделайте его из вашего объекта состояния и сделайте конструктор частным, состояние друга.

0 голосов
/ 26 августа 2010

Я думаю, что это решение дорого по производительности. Я бы создал ровно один экземпляр и изменил бы функцию создания на:

void MySingleton::reset(size_t count);
...