关于列表项及其类设计的意见
Posted
技术标签:
【中文标题】关于列表项及其类设计的意见【英文标题】:Opinions about list item and its class design 【发布时间】:2009-09-19 14:52:21 【问题描述】:我目前正在设计一个列表小部件以添加到我的小部件引擎中。由于每个元素的视觉方面都是在代码之外定义的,因此我可以重用大部分代码库。例如选项卡按钮实际上是复选框。新模板需要时间来实现,因为它们至少应该在设计应用程序中有一个查看器。
我已经有一个复选框的实现。它有 2 个状态(选中/未选中)和 5 个子状态:正常、悬停/活动、鼠标按下、禁用和状态转换。复选框模板具有文本属性、图标(可选)和边框(可以调整大小)。还有状态和子状态转换。图标和边框都是动画的。
我关心的是列表项。它们与复选框非常相似。因此,我打算为列表项使用复选框模板。但是,我需要列表项的四种模式:简单(仅文本)、带图标、带复选框和带单选按钮(单选按钮源自复选框和 IRadioButton 接口)。这里是它的结构:
IWidgetObject
|
Checkbox IRadioButton
\ /
`--------------´
|
RadioButton
我希望实现这样的东西。 ListItemBase 应该从 IWidgetObject 派生。这是合乎逻辑的还是有更好的选择。
class ListItemBase : public Checkbox
void Select() do something; Checkbox::check();
//This listitem type will have a checkbox without any text
class ListItemCheckbox : public ListItemBase, private Checkbox
check() update parents checked list; Checkbox::check();
class ListItemRadio : public ListItemBase, private RadioButton, public IRadioButton
//here is the problem
ListItemRadio 将有 2 个不同的复选框功能,我还想隐藏 ListItemBase 的 check() 函数(重命名它)。那我应该这样实现吗?
class ListItemBase : private Checkbox, public IWidgetObject
void Select() do something; Checkbox::check();
//does this even works? (layer is a variable)
using Checkbox::layer;
//This listitem type will have a checkbox without any text
class ListItemCheckbox : public ListItemBase, private Checkbox
check() update parents checked list; Checkbox::check();
class ListItemRadio : public ListItemBase, private RadioButton, public IRadioButton
//here is the problem
但是这次我在 ListItemRadio 中有 2 个 IWidgetObjects,我应该克服实现常用功能。但是 ListItemBase 必须将 IWidgetObject 的所有内容都映射到 Checkbox。
是否可以使用虚拟继承来解决这些问题,例如委托给姊妹类(复选框)。还有一个问题,虽然 IWidgetObject 看起来像一个接口,但多年来它拾取了一些常见的实现,但我认为这不会是一个问题。
还有一个问题。 Checkbox 类具有非平凡的构造函数。是否可以这样写:
ListItemBase(IWidgetContainer &container, CheckboxBP &blueprint) :
Checkbox(container, blueprint), IWidgetObject(this)
这会解决很多问题。欢迎任何想法。
感谢您阅读所有这些内容
【问题讨论】:
【参考方案1】:我不知道你的“小部件引擎”和“模板”的细节,所以也许你的设计方式现在迫使你动手(我希望不是!),但在我看来,你'在自然设计将使用包含和组合的地方重新使用继承——这是一个更可取的解决方案。即,您说的是列表项“IS-A”复选框,而自然状态是列表项“HAS-A”复选框(单选按钮也是如此)。
如果小部件引擎的设计迫使您以这种方式操作,那么最终需要多重继承也就不足为奇了——但这可能会增加其自身的复杂性,而且无论如何,子类化导致强耦合和低灵活性,而包含和组合在这些方面更好。我推荐阅读经典的Design Patterns,它很好地解释了这些问题。
不管怎样,如果你被困在这种设计中,那么,是的,就像你说的,是可能的:
ListItemBase(IWidgetContainer &container, CheckboxBP &blueprint) :
Checkbox(container, blueprint), IWidgetObject(this)
但这并不意味着 Checkbox 基类构造函数在 IWidgetObject 的构造函数之前执行:这取决于您声明基类的顺序(如果将 IWidgetObject 声明为第一个基类,则其构造函数将在另一个之前执行) .
【讨论】:
实际上在 is-a 关系中没有强制力(除了它是一个可以包含的 IWidgetObject),但我更喜欢这种方式。正如您所说,不管这种偏好如何,保留这种设计太复杂了。【参考方案2】:好的,我想出一个主意
IWidgetObject
|
ICheckbox CheckboxBase IRadioButton
| \ / | \ / |
| `-------------´ | `---------´ |
| | | | |
| Checkbox | RadioButton |
| | |
| ListItemBase |
\ | | /
`---------------´ `--------------´
| |
ListItemCheckbox ListItemRadioButton
你怎么看?
【讨论】:
以上是关于关于列表项及其类设计的意见的主要内容,如果未能解决你的问题,请参考以下文章