2011-02-22 31 views
4

我剛剛開始我的第一個相當大的Qt項目,這將主要是一堆按鈕,標籤部件和Qwt圖的屏幕。在我的應用程序中,Qt Quarterly 27中描述的面板堆棧模式看起來相當不錯。我的每個屏幕都是一個QWidget,封裝在一個由QStackedWidget顯示/隱藏的面板中。但是,它爲每個面板使用單身模式,因此它們並不是在應用程序啓動時立即創建,因此每個屏幕中都不會創建多個屏幕。在使用Qt進行GUI編程時,單例失敗?

所以我開始編碼。有面板堆棧工作。添加了一些代碼,以便動態更新小部件不會一直動態更新。有我的歷史堆棧/後退按鈕爲面板工作。一切似乎都很好,但我有一個嘮叨的煩惱:

  1. 我的代碼有異味。

我無法與這裏發佈的任何仇恨和有關單身模式的博客爭論。我想我明白了,我寫的代碼確實讓我對所有樣板文件行和全局對象感到有些dirty dirty。但是我確實不需要擔心在切換到它之前是否已經實例化一個屏幕並將其添加到我的歷史堆棧中。我只是說切換到該屏幕,它被添加到我的歷史堆棧,和魔術般的作品。

從我讀過的也有一些情況下,單身可以是值得的。這是那種特殊情況之一嗎?神奇的屏幕切換/歷史堆棧讓我覺得'是',但是我將要創建的不同單身課程的數量讓我想'不不不'。

我想只想找個人,並弄清楚如何從我的代碼現在中獲得單例模式,這樣我就不用再做了。但我不想擺脫所有的單身人士課程,只是爲了擺脫我的單身人士課程,因爲他們是EVIL [引文需要]。

任何輸入是非常感謝!

+1

不喜歡單身人士的人通常不會因爲你基本上只是使用包裹在一個類中的全局變量。儘管仇恨者說了什麼,Singleton絕對是提供全局變量訪問的更清潔的機制。一個更好的問題可能是:「在我的用戶界面邪惡中是全球狀態追蹤?」因爲,讓我們面對它,有時你只需要知道一個控件的狀態來控制另一個類中另一個控件的狀態,並通過使用全局變量來隔離這兩個模塊,就可以在兩個不同類的成員之間給出一個依賴緩衝區。 – 2011-02-22 17:07:08

+0

所以,我認爲你有一個很好的問題需要有不同的措辭。 – 2011-02-22 17:07:30

回答

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: 
    ... 
}; 

依此類推。這些get*Panel()方法仍然可以根據需要懶散地創建面板。現在,它本質上是同樣的事情,有一幫單身的,添加了一些優勢:

  • 如果我們堆棧的板兒,當堆棧被刪除,它們會自動刪除。無需擔心內存管理,這對單身人士來說總是很痛苦。
  • 甚至可以在PanelStack中實現某種「垃圾回收器」,刪除一段時間未使用的面板。或者達到某種「最大活動面板」限制時。

現在,我能想到的唯一缺點是我們現在在堆棧和麪板之間存在依賴關係。但更糟糕的是,要將實例存儲在一個類中,引入一個依賴項還是將它們存儲在全局中?如果你認爲堆棧應該獨立於面板,這聽起來合理,那麼我們可能只需要另一個類來放置所有這些東西。它可以是QApplication的子類,或者只是一些隨機的「UI管理器」類,但是將所有東西放在一個地方比將全部東西放在一起更好。

在這裏使用單例只會破壞封裝並限制整個UI的可能用途。如果我們想要這些面板有兩個窗口怎麼辦?或多個選項卡(認爲網頁瀏覽器)?單身人士會咬人。當實例在很多不相關的類中廣泛訪問時(例如數據庫連接,記錄器,池和其他典型的單例使用),它們只會非常有用。它們在用戶界面中幾乎沒有用處,因爲用戶界面幾乎總是顯而易見的:「這個東西屬於那裏,而且可能不在其他地方」。