假设我想从头开始制作自定义按钮:
所以现在我有了一个按钮,可以处理鼠标事件,绘制纯色背景,并绘制一些文本。但是现在发生了什么,如果我决定我需要一个带有背景图像而不是纯色的按钮,但是仍然知道如何绘制标签?这是单继承子类化方法失败的地方。我无法随意组合鼠标处理,标签绘图和图像绘制,我只能在继承链中选择一个细化级别。
所以我想我的问题是:实现这些单独模块的方法是什么,以便它们可以混合和匹配以创建某种后代对象,它具有以下组合的功能:所需的模块,没有别的吗?
示例,我希望能够编写如下模块:
然后能够制作一个特定的按钮,其中:a)处理鼠标,b)绘制背景,c)有标签;没有别的。
这个问题特定于如何在Objective-C或其他单继承OOP语言中执行此操作。在Ruby中,一种方法是使用mixins。
答案 0 :(得分:3)
你已经注意到继承在这里是一个坏主意。 Decorator Pattern会派上用场:你将有一个按钮类和几个“装饰”按钮的装饰器(包装并添加功能),可以任意组合。
类图:
+---------------+ innerButton
|ButtonInterface+------------------------+
+---------------+ 1 |
^ ^ |
| | |
| +-------------+ |
+------+------+ +-------+-------+ |
| BasicButton | |ButtonDecorator+------+
+-------------+ +---------------+
^ ^
| | ...
| |
+--------------------+----+ +----+------------------+
|SolidColorButtonDecorator| |LabelledButtonDecorator| ...
+-------------------------+ +-----------------------+
对象图(针对您的示例):
+----------------------------+
|MouseHandlingButtonDecorator|
+-----+----------------------+
|
1| innerButton
+-----+-------------------+
|BackgroundButtonDecorator|
+-----+-------------------+
|
1| innerButton
+-----+-----------------+
|LabelledButtonDecorator|
+-----+-----------------+
|
1| innerButton
+-----+-----+
|BasicButton|
+-----------+
答案 1 :(得分:1)
另一种选择是构图设计图案,但修改后看起来像“装饰图案”。
以下示例仅适用于绘图行为,而不适用于鼠标或键盘行为。忽略这些点,如下图所示。
注意:它更像是C ++或C#,请忽略与objective-c的细微差别。
首先,您需要一个按钮类,将“绘制”功能“委托”给成员或项目。让我们首先展示主要类。
................................................................................
..+--------------------------------+..../|..+--------------------------------+..
..| GraphicObjectClass |.../.|..| CompositeButtonClass |..
..+--------------------------------*--<..|--*--------------------------------+..
..| [+] void Draw(); <<virtual>> |...\.|..| [+] void Draw(); <<override>> |..
..+--------------------------------+....\|..+--------------------------------+..
................................................................................
假设您想要一个按钮,并且:
第二个图表显示了单独的“模块”或类别:
................................................................................
..+--------------------------------+............................................
..| GraphicObjectClass |............................................
..+--------------------------------+............................................
..| [+] void Draw(); <<virtual>> |............................................
..+---------------*----------------+............................................
..................|.............................................................
..................^.............................................................
................./.\............................................................
................/...\...........................................................
.............../--+--\..........................................................
..................|.............................................................
..+---------------*----------------+.../|...+--------------------------------+..
..| ButtonComponentClass |../.|...| SolidColorButtonClass |..
..+--------------------------------+-<..|-*.+--------------------------------+..
..| [+] void Draw(); <<virtual>> |..\.|.|.| [+] void Draw(); <<override>> |..
..+--------------------------------+...\|.|.+--------------------------------+..
..........................................|.....................................
..........................................|.+--------------------------------+..
..........................................|.| LabeledButtonClass |..
..........................................|.+--------------------------------+..
..........................................*-* [+] void Draw(); <<override>> |..
..........................................|.+--------------------------------+..
..........................................|.....................................
..........................................|.+--------------------------------+..
..........................................|.| BorderButtonClass |..
..........................................|.+--------------------------------+..
..........................................*-* [+] void Draw(); <<override>> |..
............................................+--------------------------------+..
................................................................................
让我们将组件集成到按钮,请注意我为其他关联创建了一个独立的继承关联图表。
.......................................................................................
.+--------------------------------------------+.....+--------------------------------+.
.| 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();
}
只是一个建议。
干杯。