Версия реализации класса Singleton - PullRequest
0 голосов
/ 23 января 2012

Хотелось бы обсудить нюансы реализации известного шаблона проектирования Singleton.Здесь есть две реализации в C ++:

http://www.codeproject.com/Articles/1921/Singleton-Pattern-its-implementation-with-C

и еще одна такая:

#ifndef __SINGLETON_HPP_
#define __SINGLETON_HPP_

template <class T>
class Singleton
{
public:
  static T* Instance() {
      if(!m_pInstance) m_pInstance = new T;
      assert(m_pInstance !=NULL);
      return m_pInstance;
  }
protected:
  Singleton();
  ~Singleton();
private:
  Singleton(Singleton const&);
  Singleton& operator=(Singleton const&);
  static T* m_pInstance;
};

template <class T> T* Singleton<T>::m_pInstance=NULL;

#endif

Если мы сравним эти версии, какие у них есть преимущества и недостаткии, в конце концов, какая версия предпочтительнее?

Ответы [ 2 ]

1 голос
/ 23 января 2012

Основные различия между этими двумя реализациями:

  • первый добавляет избыточный флаг, чтобы сообщить вам, является ли указатель нулевым, и поэтому занимает немного больше памяти, чем нужно;
  • второй вообще не синглтон: ничто не мешает T иметь открытый конструктор, тем самым нарушая ограничение синглтона.

Основные проблемы с обоимиони (за исключением того факта, что синглтон никогда не является хорошей идеей):

  • конструкция не является поточно-ориентированной;вызов Instance() из двух потоков может привести к созданию двух объектов;
  • утечка памяти;они динамически создают объект с помощью new, но никогда не вызывают delete.

В C ++ очень трудно безопасно управлять временем жизни глобально доступного объекта;по этой причине (и многие другие ) я бы порекомендовал вообще избегать анти-паттерна Singleton.Создавайте объекты в хорошо управляемых областях и передавайте ссылки там, где это необходимо.

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

static Singleton & Instance() {
    static Singleton instance;
    return instance;
}

Это будет создано при первом вызове функции, и компилятор C ++ 11 должен убедиться, что это потокобезопасно.Оставшаяся проблема заключается в том, что экземпляр может быть уничтожен раньше других статических объектов, что приведет к катастрофе, если его деструкторы попытаются получить к нему доступ.

0 голосов
/ 23 января 2012

По сути, обе реализации одинаковы. Реализация на CodeProject предусматривает 2 вещи:

  • флаг статуса синглтона, который позволяет пометить синглтон как «старый» снаружи (а затем правильно восстановить его изнутри)
  • метод getInstance, который не является чем-то особенным с точки зрения синглтона. Однако это делает код более читабельным для других людей И для себя через некоторое время.

Просто разница между
Cat::meow(); и
Cat::getInstance()->meow()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...