Допустим, нам нужен только один экземпляр некоторого класса в нашем проекте.Есть несколько способов сделать это.
Лучшее решение:
Переменная в main, которую вы передаете в качестве параметра всем необходимым функциям, будет другой.
a) Порядок инициализации статических элементов в разных единицах не определен.Таким образом, полностью статическая инициализация членов не может использовать статические члены / функции из других модулей.И синглтон не имеет этой проблемы.
Синглтоны имеют эту проблему, если их конструктор / деструктор обращается к другой глобальной статической переменной продолжительности жизни.
b) Нам нужно разобратьсяс потоками для getInstance () Sigleton.Однако в полностью статическом классе такой проблемы нет.
Не правда ли, проблема?Если вам это известно, просто добавьте соответствующие блокировки в код.
c) Доступ к методам выглядит немного иначе.Foo :: бар ();vs Foo :: getInstance () -> bar ();Как правило, sigleton может возвращать NULL, чтобы идентифицировать, что были некоторые проблемы с конструкцией объекта, а статический класс не может.
Я бы заставил свой getInstance () возвращать ссылку.Тогда нет никакой неоднозначности, если указатель равен NULL.Это или сработало или бросило исключение.Также это приводит к созданию схемы, в которой уничтожение корректно вызывается для экземпляра (не принимайте это как совет по использованию Singleton, я бы избегал его, если это возможно (но если вы его используете, сделайте его аккуратным)).
d) Определение класса выглядит немного неуклюжим с кучей статики для статического класса.
Нет более сложного, чем правильная запись синглтона.
Проблема с обоими этими методамиявляется то, что они оба обращаются к global mutable state
, и, следовательно, использование этих объектов «одного экземпляра» другими объектами скрыто от пользователя.Это может привести к проблемам с тестированием (TDD требует возможности имитировать внешнюю функциональность, но global mutable state
не позволяет тестировщику имитировать внешние зависимости (легко)).
Любой объект, не являющийся POD, имеет конструкторэто может потенциально вызвать исключение.Таким образом, для объектов в глобальном пространстве имен это означает, что исключения могут быть сгенерированы до того, как будет введена функция main () (это может привести к трудностям при поиске ошибок (если у вас много глобальных объектов (вы должны ставить точки останова везде)). Нота же проблема существует с синглтоном, который лениво оценивается: если при первом использовании он выдает, как исправить это, чтобы при последующей попытке не сработал? Оу, будет ли ваше приложение продолжать генерировать каждый раз, когда извлекается синглтон?