Синглтон или передача указателей на статическую ссылку в менеджере

0

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

Теперь этот указатель класса не сразу полезен для дочерних элементов, но он полезен для детей-детей, поэтому все, что происходит, это то, что оно прошло.

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

Существует множество типов соединений (30+), и никто из них не заботится о классе полезности. Тем не менее, они будут использовать классы (на данный момент, всего 2), которые заботятся о классе полезности.

Я не уверен, что каждый тип связи должен обременять себя чем-то, на что он не заботится, просто ради нескольких классов, которые он может использовать.

  • 0
    Итак, есть класс, у него есть ребенок, и у него тоже есть ребенок. Основной класс использует ссылку, как и младший ребенок, или это просто младший ребенок?
  • 0
    класс A -> класс B -> класс C. Класс «A» содержит экземпляр служебного класса и передает его классу B, который передает его классу C. Только класс C фактически использует указатель экземпляра вспомогательного класса.
Теги:
singleton

3 ответа

2
Лучший ответ

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

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

Я не знаю характера вашего класса, но мне кажется разумным, что каждое соединение должно иметь ссылку (или указатель) на диспетчер соединений, который управляет им. На всякий случай.

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

Также имеет смысл передать ссылку на диспетчер подключений на конструктор общего предка соединений, если он есть (каким он должен быть). Таким образом, у вас больше нет классов 30+, которые ссылаются на то, что им действительно не нужно, а всего лишь на один абстрактный класс, на котором они основаны.

И если вы действительно хотите сделать что-то одноточечное, тогда лучше иметь какой-то статический метод с параметром, возвращающим ссылку, а не только статическим методом:

static UtilityClass *getInstance(int id);
// not static UtilityClass *getInstance();

Даже если вы не используете параметр id прямо сейчас, он может стать очень полезным позже, когда вам понадобится несколько экземпляров. У вас может быть какая-то таблица или хеш-карта, которая отображает идентификатор в экземпляр. Вы даже можете добавить метод, который создает или заменяет экземпляр для определенного идентификатора, что может быть очень полезно для модульного тестирования. Обратите внимание, что этот подход по-прежнему имеет по крайней мере следующие недостатки одноэлементного шаблона:

  • Он подвержен различным проблемам с резьбой.
  • Он по-прежнему скрывает зависимости ваших классов: то есть вы не можете сказать, что класс использует, просто просматривая его API.

Трудно дать больше советов, не глядя на код.

  • 0
    Он статичен, потому что это встроенное приложение, и поэтому большая часть управления памятью выполняется во время компиляции, а не во время выполнения - нет кучи как таковой, поэтому такие вещи, как «new», не используются. Все соединения имеют общий базовый класс, и он используется диспетчером соединений в качестве интерфейса.
  • 0
    Служебный класс также выделяет ресурсы для классов, которые зависят от него, поэтому его экземпляр должен быть только один.
Показать ещё 4 комментария
1

Синглтон против Статического

Хороший пример использования singleton: вы хотите, чтобы для класса выполнялся только один экземпляр, например менеджер текстур, менеджер шейдеров, диспетчер пула соединений и т.д. (См. Шаблон:

В качестве примера возьмем диспетчер пула соединений: мы хотим создать единый пул соединений, которые управляются и повторно используются любым другим объектом, требующим подключения в нашем коде, поэтому мы создаем Singleton-класс ConnectionPoolManager, скажем, 32 соединения. Теперь это позволяет каждому объекту, которому требуется подключение, использовать метод, например getFreeConnection, из Singleton для ConnectionPoolManager, чтобы получить правильное соединение, которое затем может быть использовано по мере необходимости. Это позволяет ConnectionPoolManager быть единственной частью кода в любом месте, которое имеет какое-либо отношение к запуску остановки и, в противном случае, управлению соединениями для вашего кода.

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

Что касается вашего конкретного случая, вы указываете, что из классов 30+ только пара требует класса утилиты: зависимость от singleton или static class полностью зависит от вашего дизайна и стиля. Если вы пожелаете универсального способа сделать это, с возможностью изменения позже, я бы использовал синглтон. Если вы знаете, что статический класс будет достаточным и не потребует повторной модификации позже, тогда перейдите к нему или, если у вас есть особая симпатия к тому или иному, используйте его. Могут также существовать ограничения на аппаратное и программное обеспечение и сведения, которые рекомендуют друг другу, однако в настоящий момент это не так.

Дайте мне знать, если вам нужна дополнительная информация, или если есть какие-либо подробности, которые, по вашему мнению, могут повлиять на ваш выбор так или иначе, и я могу предоставить информацию о плюсах и минусах для каждого подхода в соответствии с вашими потребностями :)

  • 0
    Я поднял ваш ответ, так как это полезный пост, но я думаю, что вы упустили смысл исходного вопроса, который заключался в разнице между синглтоном (так что класс выполняет singleton :: getInstance) и статическим экземпляром класса (например, static XUtilityClass utility; // Совместно используется всеми экземплярами этого класса)
  • 1
    Ах, нет, я сформулировал сравнение извинения, я исправлю это. Ура кальмар :)
Показать ещё 2 комментария
1

Если я правильно вас понимаю, на верхнем уровне находится диспетчер подключений. Он содержит статический класс, который будет полезен позже.

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

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

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

Я назову их: Менеджер (содержит "статический класс") → Соединение → Утилита

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

Поэтому, когда Connection построит классы Utility, для классов Utility потребуется только бит информации, который им нужен для работы (в данном случае эталонный параметр для класса, который является статичным внутри Менеджера). Они также должны принять это путем ссылки. Соединение имеет ссылку на класс Менеджера и может предоставить конструктору для Утилиты информацию, необходимую для работы.

Причина, по которой я предлагаю этот подход:

  • Классы Connections/Utility не заботятся о том, является ли менеджер синглом (открывает возможности позже, если вам нужно несколько менеджеров)
  • Утилита не заботится о статическом статическом классе. Им нужна только ссылка на конкретный класс, в котором они нуждаются.
  • Менеджер решает, как это или его содержащиеся данные необходимо выделить.

И, наконец:

  • Единственный класс, который имеет основания знать о двух других основных классах, - это класс Connections. Кажется разумным, что он может знать, какой менеджер управляет им (и, следовательно, некоторая информация о интерфейсе). Он также знает, какие классы Utility он потребует и что им потребуется в плане параметров конструкции и других требований к интерфейсу.

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

Мой 2c.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню