用Qt进行GUI编程中的单身人士EVIL?

jjf*_*ine 4 singleton qt design-patterns

我刚刚开始我的第一个相当大的Qt项目,它将主要是一堆带按钮,标签小部件和Qwt Plots的屏幕.Qt Quarterly 27中描述的面板堆栈模式对我的应用来说似乎相当不错.我的每个屏幕都是一个封装在Panel中的QWidget,它由QStackedWidget显示/隐藏.但是,它为每个Panel 使用单例模式,因此它们不会在应用程序启动时立即创建,因此不会创建多个屏幕.

所以我开始编码.让面板堆工作.添加了一些代码,以便动态更新小部件不会一直动态更新.让我的历史堆栈/后退按钮适用于面板.一切似乎都很好,但我有一个唠叨的担忧:

  1. 我的代码闻起来.

我无法与这里发布的任何仇恨以及关于单身人士模式的博客争论.我想我得到了它,我编写的代码确实让我觉得所有样板线和全局对象都有点脏.但我确实不必担心在切换到屏幕之前是否已经实例化屏幕并将其添加到我的历史堆栈中.我只是说切换到那个屏幕,它被添加到我的历史堆栈中,并且魔术起作用.

从我所读到的,还有一些案例,单身人士是值得的.这是特殊情况吗?神奇的屏幕切换/历史堆栈让我觉得"是",但是我要创建的不同单身类的绝对数量让我想到"不,不,不,不".

我想正义的人并弄清楚如何获得Singleton模式了我的代码,现在这样我就不必在以后做.但我不想摆脱我的所有单身人士课程,只是为了摆脱我的单身人士课程,因为他们是EVIL [需要引证].

任何输入都非常感谢!

Ser*_*nov 6

我并不讨厌单身人士,但这听起来像是一个对他们毫无用处的情况.我不明白为什么那篇文章中有这么多单身人士.

首先,PanelStack本身就是一个单身人士.为什么?如果那是你的主要小部件,那么只需在main()中的堆栈上创建它,它既更干净又更快.如果它是更复杂的UI的一部分,那么将其作为该UI的成员放在那里.常规类在这里很好,使单例仅限制其可能的用途.

然后,每个面板也是单身?在这一点上,即使是单身爱好者也应该开始觉得他们已经有太多了.这可能是你首先提出这个问题的原因.让我们看看单身人士在这里给出的真正优势.好吧,我可以从那篇文章中找到的唯一优势是能够在需要时随意创建面板.这实际上是一件好事,但事实上,懒惰的创作和单身是不同的模式,尽管一个人经常使用另一个.

为什么不把所有这些面板放在一些普通的容器中呢?在这种情况下,PanelStack看起来像是一个完美的候选者.毕竟,这是存放面板的地方.而不是一堆单身人士,让我们在PanelStack中创建一堆方法:

class PanelStack : public QWidget
{
  Q_OBJECT

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

private:
  ...
};
Run Code Online (Sandbox Code Playgroud)

等等.这些get*Panel()方法仍然可以根据需要懒洋洋地创建面板.现在,它与拥有一堆单身人士基本相同,增加了一些优势:

  • 如果我们将面板设为子堆栈,则在删除堆栈时会自动删除它们.无需担心内存管理,这对单身人士来说总是很痛苦.
  • 您甚至可以在PanelStack中实现某种"垃圾收集器",删除一段时间未使用过的面板.或者达到某种"最大活动面板"限制时.

现在,我能想到的唯一缺点是我们现在在堆栈和面板之间存在依赖关系.但更糟糕的是,将实例存储在一个类中,引入依赖关系,还是将它们存储在全局?如果你认为堆栈应该独立于面板,这听起来合理,那么我们可能只需要另一个类来放置所有这些东西.它可能是QApplication的子类,或者只是一些随机的"UI管理器"类,但是将所有东西存放在一个地方比在全球存储一切更好.

在这里使用单例只会破坏封装并限制整个UI的可能用途.如果我们想要这些面板有两个窗口怎么办?或多个标签(想想网络浏览器)?单身人士会苦苦挣扎.当实例被广泛访问许多不相关的类(想想数据库连接,记录器,池和其他典型的单例用途)时,它们才真正有用.它们在用户界面中大多无用,因为使用用户界面几乎总是很明显"这个东西属于那里,而且可能没有其他地方".