Являются ли Singletons EVIL в программировании GUI с помощью Qt? - PullRequest
4 голосов
/ 22 февраля 2011

Я только начинаю свой первый довольно большой проект Qt, который в основном будет состоять из нескольких экранов с кнопками, виджетами вкладок и графиками Qwt.Шаблон стека панелей, описанный в Qt Quarterly 27 , кажется довольно хорошим для моего приложения.Каждый из моих экранов - это QWidget, инкапсулированный в Panel, который отображается / скрывается QStackedWidget.Однако он использует одноэлементный шаблон для каждой панели, чтобы не все они создавались сразу при запуске приложения, и чтобы не было создано более одного экрана.

Итак, я начал кодировать.Получил панель стека работает.Добавлен некоторый код, чтобы динамически обновляемые виджеты не обновлялись постоянно.Получил мою кнопку стека истории / назад для панелей.Кажется, все просто отлично, но у меня есть одно ноющее беспокойство:

  1. Мой код пахнет.

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

Из того, что я прочитал, есть также некоторые случаи, когда одиночные игры могут быть полезны.Это один из тех особых случаев?Волшебный стек переключения / истории заставляет меня думать «да», но огромное количество различных синглтон-классов, которые я собираюсь создать, заставляет меня думать «НЕТ, НЕТ, НЕТ, НЕТ».

Я хочу простоПоднимитесь и выясните, как получить шаблон синглтона из моего кода сейчас , чтобы мне не пришлось делать это позже.Но я не хочу избавляться от всех моих синглтон-классов, просто чтобы избавиться от моих синглтон-классов, потому что они ЗЛО [цитата нужна].

Любой вклад очень ценится!

1 Ответ

6 голосов
/ 22 февраля 2011

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

Во-первых, PanelStack сам по себе является синглтоном.Зачем?Если это ваш главный виджет, просто создайте его в стеке в main (), который будет чище и быстрее.Если он является частью более сложного пользовательского интерфейса, поместите его в качестве члена этого пользовательского интерфейса.С обычным классом здесь все в порядке, делая его синглтоном, только ограничивая его возможное использование.

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

Почему бы просто не поместить все эти панели в какой-то общий контейнер?В этом случае PanelStack выглядит как идеальный кандидат для этого.Это то самое место, где хранятся панели.Вместо группы синглетонов, давайте создадим группу методов в PanelStack:

class PanelStack : public QWidget
{
  Q_OBJECT

public:
  int addPanel(AbstractPanel *);
  void showPanel(int);
  RecordingsPanel *getRecordingsPanel();
  ReecrdingDetailsPanel *getRecordingDetailsPanel();

private:
  ...
};

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

  • Если мы сделаем панели дочерними по стеку, они будут автоматически удалены при удалении стека.Не нужно беспокоиться об управлении памятью, которое всегда является проблемой с одиночками.
  • Вы можете даже реализовать своего рода «сборщик мусора» в PanelStack, который удаляет панели, которые не использовались в течение некоторого времени.Или когда достигается какое-то ограничение на «максимальное количество активных панелей».

Теперь единственный недостаток, о котором я могу думать, это то, что у нас теперь есть зависимость между стеком и панелями.Но что хуже: хранить экземпляры в одном классе, вводить зависимости или хранить их глобально?Если вы думаете, что стек должен быть независимым от панелей, что звучит разумно, то нам, вероятно, просто нужен другой класс, чтобы поместить все эти вещи. Это может быть подкласс QApplication или просто некоторый случайный класс «UI manager», новсе же лучше хранить все в одном месте, чем хранить все глобально.

Использование синглетонов здесь только нарушает инкапсуляцию и ограничивает возможное использование всего пользовательского интерфейса.Что если мы хотим иметь два окна с этими панелями?Или несколько вкладок (например, веб-браузер)?Синглтоны будут сильно кусаться.И они действительно полезны только тогда, когда к экземпляру обращаются широко во многих не связанных между собой классах (например, соединения с БД, регистраторы, пулы и другие типичные синглтоны).Они в основном бесполезны в пользовательском интерфейсе, потому что в пользовательском интерфейсе почти всегда очевидно, что «эта вещь принадлежит там, и, вероятно, больше нигде».

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