Синглтон, который не доступен во всем мире - PullRequest
3 голосов
/ 13 октября 2010

Мне просто интересно, как лучше всего избавиться от глобально доступной статической функции getInstance () в синглтоне.Я не хочу, чтобы к моим классам Singleton обращались из каждой точки моей программы.

Возможно, я подумал о том, чтобы иметь публичную статическую функцию create (), которая создает один объект и возвращает его, но никто не может вызвать этот метод дважды.

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

Есть ли другой способ добиться того, чего я хочу?

Ответы [ 3 ]

3 голосов
/ 13 октября 2010

Вы сказали, что «создание одного раза повредит все приложение». Мой ответ: так что не делайте больше одного. В 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
}
2 голосов
/ 13 октября 2010

Удалите Singleton и снова вставьте прилагаемую функцию туда, где она должна быть, с соответствующими модификаторами доступа.

См. Здесь окончательный список причин, по которым синглтоны являются антипаттерном .

Особенно важно - см. здесь о различиях между синглтоном (паттерн GoF) и синглтоном (как в «есть один и только один из меня»).

1 голос
/ 13 октября 2010

Вы можете сделать ваш метод 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();
  }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...