簡體   English   中英

接口層次結構設計模式?

[英]Interface hierarchy design pattern?

我正處於開發具有圖形用戶界面的C ++多平台(移動)應用程序的初期階段。 我正在嘗試找到一種抽象實際UI /窗口實現的好方法。 到目前為止,基本上是我嘗試過的:

我創建了一個界面層次結構

Screen
 +Canvas
 +Form
   +Dialog
Control
 +EditBox
 +CheckBox
 +...

我還有一個Application類,該類基本上使用所有這些接口來實現UI邏輯。 Application類還提供了用於創建UI類實例的抽象工廠方法。

這些接口都有實現。 例如,對於Windows Mobile,Win32Form實現Form,Win32Canvas實現Canvas,Win32Dialog實現Dialog。 如您所見,問題在於實現失去了層次結構,即Win32Dialog不擴展Win32Form。

例如,這在方法Form :: addControl(Control&ctrl)中成為問題。 在Windows Mobile版本的應用程序中,我知道ctrl參數是Win32 ...控件實現之一。 但是由於層次結構丟失了,所以無法知道它是Win32EditBox還是Win32CheckBox,我真的需要知道它們才能在控件上執行任何平台特定的操作。

我正在尋找的是有關如何解決此問題的設計模式。 注意,不需要保留此接口層次結構解決方案,這只是我當前的方法。 我將采用能解決將UI邏輯與幾種不同的UI實現分開的問題的方法。

請不要告訴我使用這個或那個UI庫; 我喜歡從頭開始編寫代碼,而我是出於學習經驗... ;-)

我的一些靈感:

不要從屏幕繼承Form。 它不是“是”房地產。

 Screen
 Canvas
 GUIObject
    Form
       Dialog
    Control
       Button
       EditBox
       CheckBox
       ...
       Panel

更詳細的描述:

屏幕

  • “有”帆布
  • 提供顯示特定功能
  • 不要試圖從Canvas繼承

帆布

  • 您的抽象繪圖環境
  • 目標是屏幕畫布,表單畫布,圖像,內存...

GUIObject

  • 在某些層次結構中
  • 通常提供一些自省功能
  • 通常提供消息處理界面

形成

  • 在某些實際上稱為“對話框”的工具包中
  • 您可以在其上繪制的“具有”畫布
  • “具有”控件列表或工作區面板
  • “具有”標題,滾動條等

對話

  • 我喜歡將對話框稱為標准化的YesNo,OpenFile等,基本上是簡化的Form(沒有關閉按鈕,沒有菜單等)
  • 可以或不可以從Form繼承

控件是不言自明的(面板是內部帶有可選滾動條的控件的區域)。

這應該工作。 然而,如何利用每個平台的特定功能而不破壞該接口的通用性和/或易用性是困難的部分。 我通常嘗試將所有圖形與這些基本類分開,並具有一些特定於平台的“畫家”,可以使用每個基本對象並以特定於平台的方式對其進行繪制。 另一個解決方案是為每個平台使用並行層次結構(我傾向於避免這種情況,但有時需要使用-例如,如果需要包裝Windows句柄)或“功能位”方法。

您可以使用遏制。 例如,實現Dialog的類將包含Win32Dialog作為屬性,而實現Form的類將包含Win32Form 對Dialog或Form成員的所有訪問都將委派對包含的類的訪問。 這樣,如果這對您的項目有意義,您仍然可以使DialogForm繼承。

話雖如此,我發現您的界面設計有些奇怪。 如果我理解正確(我可能還沒有,請糾正我),Dialog從Form繼承,Form從Screen繼承。 問問自己,以驗證此設計: 對話框也是表格嗎? 它也是屏幕嗎? 僅當is-a關系有意義時才應使用繼承。

解決此問題的GOF模式是橋接模式。 Konamiman的答案對此進行了解釋,您使用委派/包含來抽象問題之一。

我花了多年的時間進行手機開發。

我的建議是不要陷入“抽象”陷阱!

這樣的框架比僅在每個平台上實現應用程序要更多的代碼(並且令人討厭,不好玩!)。

抱歉; 您正在尋找樂趣和經驗,我想說有很多有趣的地方可以得到它。

首先,主要問題似乎在於您的“抽象”層中沒有抽象。

實現與操作系統提供的控件相同的控件,僅在其名稱前加上“ Win32”前綴並不構成抽象。

如果您不打算真正簡化和概括該結構,那么為什么還要首先編寫一個抽象層呢?

為了做到這實際上是有用的 ,你應該寫,代表需要概念的類。 然后在內部將它們映射到必要的Win32代碼。 不要僅僅因為Win32有一個Form類或Window類。

其次,如果您需要精確的類型,我想放棄OOP方法,並使用模板。

代替功能

Form::addControl(Control &ctrl)

限定

template <typename Ctrl_Type>
Form::addControl(Ctrl_Type &ctrl)

現在,該函數知道控件的確切類型,並且可以執行所需的任何特定於類型的操作。 (當然,如果必須將控件保存到控件的列表中,則會再次丟失類型信息。但是至少可以進一步傳播類型信息,這可能會有所幫助。

該集合甚至可以存儲諸如boost::variant對象之類的東西,這將使您甚至可以保留一些類型信息。

否則,如果您要使用OOP路線,則至少要正確進行 如果您要將EditBoxes和CheckBoxes都隱藏在一個通用的IControl接口后面,那應該是因為您不需要確切的類型。 該接口應該是您所需要的。 這就是接口的意義。

如果不遵守該合同,那么如果您一直都在貶低實際類型,那么您良好的OOP層次就是有缺陷的。

如果您不知道要達到的目標,將很難成功。 這樣做的目的是嘗試編寫“ Windows公開的用戶界面的抽象”,但是您什么都沒有做,因為Windows 已經公開了。 如果Windows公開的抽象不符合您的需求,請編寫抽象層。 如果您想要一個不同的層次結構,或者根本不需要層次結構,或者不希望任何形式都是Form或Control的層次結構,那么編寫抽象層是有意義的。 如果只需要“與Win32相同,但使用我的命名約定”的圖層,那是在浪費時間。

因此,我的建議是:從您希望GUI層如何工作開始。 然后擔心如何將其映射到基礎Win32原語。 忘記您曾經聽說過的表單,對話框或編輯框,甚至控件或窗口。 所有這些都是Win32概念。 定義在您的應用程序中有意義的概念。 沒有規則要求GUI中的每個實體都必須從公共Control類或接口派生。 沒有規則必須將所有東西都放置在一個“窗口”或“畫布”中。 這是Windows使用的約定。 編寫一個對有意義的API。

然后根據可用的Win32原語弄清楚如何實現它。

有趣的問題,所以有幾點想法:

  • 首先:您可以始終使用MI,以便Win32Dialog可以同時繼承Win32Form和Dialog,因為您隨后獲得了漂亮的菱形,因此需要虛擬繼承
  • 第二:嘗試避免MI;)

如果要使用特定的控件,那么您使用的是Win32特定的方法,對嗎? 希望您不要在談論up_casting:/

那么,當Win32特定的控制方法可以得到更精確的類型時,又如何將其交給通用對象呢?

您也許可以在這里應用得墨meter耳定律。 Facade方法配合使用時效果很好。

這個想法是,您實例化一個Win32Canvas,然后要求畫布添加一個對話框(帶有一些參數),但是您實際上並沒有親自操作該對話框,因此,畫布知道其實際類型並可以執行特定於平台的操作。

如果您想稍微控制一些事情,請讓畫布返回一個Id,您以后將使用該Id定位此特定對話框。

如果canvas從模板(平台上的模板)繼承,則可以緩解大多數常見的實現。

另一方面: Facade實際上意味着膨脹的界面...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM