2013-02-14 66 views
1

假設我想從頭開始創建一個自定義按鈕:哪種設計模式適合從模塊化子件創建對象?

  • BasicButton:NSObject的
    所以我創建了知道如何處理鼠標事件和消息轉發給有興趣的接收者點擊該按鈕時(類通過授權,目標/行動,通知,無論如何)。
  • SolidColorButton:BasicButton:NSObject的
    我的按鈕現在的作品,但它是無形的,所以我決定畫一個堅實的背景,使按鈕壽命(在UI設計方面不是很好,但讓我們假裝)。
  • LabelledButton:SolidColorButton:BasicButton:NSObject的
    現在讓我們說,我想在按鈕上添加一個標籤,所以我創建了一個另一個子集中,可以在按鈕上繪製文本。

所以現在我有一個按鈕,它可以處理鼠標事件,繪製一個堅實的背景,並繪製一些文本。但是,如果我決定需要一個具有背景圖像的按鈕而不是純色,但是仍然知道如何繪製標籤,現在會發生什麼?這是單繼承子類化方法失敗的地方。我不能隨意組合鼠標處理,標籤繪製和圖像繪製,我只能選擇繼承鏈中細化的級別。

所以我想我的問題是:什麼是實現這些獨立的模塊,這樣則可以將它們混合和匹配,以建立某種形式的具有所需模塊,別無其他的組合特徵後代對象的方式?

例子,我希望能夠寫這樣的模塊:

  • 鼠標操作
  • 鍵盤操作
  • 堅實的背景
  • 圖像背景
  • 標籤

,然後必須使一個特定的按鈕,其的能力:1)處理鼠標,b)中繪製一個背景和c)具有的標籤;沒有別的。

這個問題是特定於如何在Objective-C或其他單一繼承OOP語言中執行此操作。在Ruby中,一種方法是使用mixins。

回答

3

你已經注意到繼承在這裏是一個壞主意。 Decorator Pattern會派上用場:你將有一個按鈕類和幾個裝飾器來「裝飾」按鈕(包裝它並添加功能),並可以任意組合。

類圖:

+---------------+  innerButton 
|ButtonInterface+------------------------+ 
+---------------+ 1      | 
     ^^       | 
     | |       | 
     | +-------------+    | 
+------+------+ +-------+-------+  | 
| BasicButton | |ButtonDecorator+------+ 
+-------------+ +---------------+ 
        ^  ^
        |   | ... 
        |   | 
+--------------------+----+ +----+------------------+ 
|SolidColorButtonDecorator| |LabelledButtonDecorator| ... 
+-------------------------+ +-----------------------+ 

對象圖(爲您的示例):

+----------------------------+ 
|MouseHandlingButtonDecorator| 
+-----+----------------------+ 
     | 
    1| innerButton 
+-----+-------------------+ 
|BackgroundButtonDecorator| 
+-----+-------------------+ 
     | 
    1| innerButton 
+-----+-----------------+ 
|LabelledButtonDecorator| 
+-----+-----------------+ 
     | 
    1| innerButton 
+-----+-----+ 
|BasicButton| 
+-----------+ 
+1

+1。您可以檢查使用這種方法的VisualWorks Smalltalk GUI框架實現。 – 2013-02-14 13:00:04

+0

+1我已經使用裝飾模式代碼函數,而不是圖形,界面,你的答案,使我必須研究更多關於它;-) – umlcat 2013-02-14 17:55:44

1

另一個替代方案是所述組合物的設計模式,然而,修改,以看起來像「裝飾模式」。

以下示例僅適用於繪圖行爲,不適用於鼠標或鍵盤行爲。忽略這些點,如下圖所示。

注意:它更像C++或C#,請忽略與objective-c的細微差異。

首先,您需要一個將「委託」成員或項目的「繪製」函數的按鈕類。首先讓我們展示主類。

................................................................................ 
..+--------------------------------+..../|..+--------------------------------+.. 
..|  GraphicObjectClass  |.../.|..|  CompositeButtonClass  |.. 
..+--------------------------------*--<..|--*--------------------------------+.. 
..| [+] void Draw(); <<virtual>> |...\.|..| [+] void Draw(); <<override>> |.. 
..+--------------------------------+....\|..+--------------------------------+.. 
................................................................................ 

讓我們假設你想有一個按鈕,:

  • 「模塊級」繪製邊框
  • 「模塊級」繪製背景,wheter純色或圖案
  • 「模塊類」繪製的文本標籤,粗體,斜體,字體名稱

第二個圖,示出了分隔符

................................................................................ 
..+--------------------------------+............................................ 
..|  GraphicObjectClass  |............................................ 
..+--------------------------------+............................................ 
..| [+] void Draw(); <<virtual>> |............................................ 
..+---------------*----------------+............................................ 
..................|............................................................. 
..................^............................................................. 
................./.\............................................................ 
................/...\........................................................... 
.............../--+--\.......................................................... 
..................|............................................................. 
..+---------------*----------------+.../|...+--------------------------------+.. 
..|  ButtonComponentClass  |../.|...|  SolidColorButtonClass  |.. 
..+--------------------------------+-<..|-*.+--------------------------------+.. 
..| [+] void Draw(); <<virtual>> |..\.|.|.| [+] void Draw(); <<override>> |.. 
..+--------------------------------+...\|.|.+--------------------------------+..  
..........................................|..................................... 
..........................................|.+--------------------------------+.. 
..........................................|.|  LabeledButtonClass  |.. 
..........................................|.+--------------------------------+.. 
..........................................*-* [+] void Draw(); <<override>> |.. 
..........................................|.+--------------------------------+.. 
..........................................|..................................... 
..........................................|.+--------------------------------+.. 
..........................................|.|  BorderButtonClass  |.. 
..........................................|.+--------------------------------+.. 
..........................................*-* [+] void Draw(); <<override>> |.. 
............................................+--------------------------------+.. 
................................................................................ 

讓我們的組件集成到按鈕,請注意,我做一個不同的圖表繼承的關聯,從其他協會:該做的separatly E「模塊」或類。

....................................................................................... 
.+--------------------------------------------+.....+--------------------------------+. 
.|    CompositeButtonClass   |.....|  SolidColorButtonClass  |. 
.+--------------------------------------------+.....+--------------------------------+. 
.| [+] ButtonComponentClass* Background  *-----* [+] void Draw(); <<override>> |. 
.|           |.....+--------------------------------+. 
.| [+] ButtonComponentClass* Border   *---*.................................... 
.|           |...|.+--------------------------------+. 
.| [+] ButtonComponentClass* Label   *-*.|.|  LabeledButtonClass  |. 
.+--------------------------------------------+.|.|.+--------------------------------+. 
.| [+] void Draw();    <<virtual>> |.|.+-* [+] void Draw(); <<override>> |. 
.+--------------------------------------------+.|...+--------------------------------+. 
................................................|...................................... 
................................................|...+--------------------------------+. 
................................................|...|  BorderButtonClass  |. 
................................................|...+--------------------------------+. 
................................................*---* [+] void Draw(); <<override>> |. 
....................................................+--------------------------------+. 
....................................................................................... 

現在,您將擁有一個按鈕類,它將「委託」成員或項目的「繪製」函數。首先讓我們展示主類。

virtual /* override */ void CompositeButtonClass::Draw() 
{ 
    // [Background Draw]  
    this->Background->Draw(); 

    // [Border Draw] 
    this->Border->Draw(); 

    // [Label Draw] 
    this->Label->Draw(); 
} 

只是一個建議。

乾杯。