面向对象设计问题:GUI 应用程序

5
各位,我正在为一个应用程序编写GUI,其中包含一个CD容器来插入CD。目前我对面向对象设计还不是很清楚,所以我需要一些帮助来澄清我的理解。
首先,我使用观察者模式构建了抽象的Model和View类,以及具体的模型(CD容器)和具体的视图(CD容器视图)。然后我开始使用wxwidget框架为CD容器和其他GUI控件(如MainFrame)设计图形外观或布局(CDContainerWidget,从wxPanel继承而来)。
现在我有三个类:CDContainerModel(CD容器),CDContainerView(观察者模式的类),以及CDContainerWidget(GUI控件)。然后我对CDContainerViewCDContainerWidget应该怎么处理感到不太清楚?
我认为CDContainerWidget和CDContainerView都需要CDContainerModel。我考虑了四种方法,但不知道哪种更合适:
1)将CDContainerWidget作为成员变量关联到CDContainerView中,然后将CDContainerView作为成员变量放入主窗口中。
(以下省略)
class CDContainerView:
  def __init__:
     self.gui=CDContainerWidget

class MainFrame:
  def __init__:
     CDContainerView

2). CDContainerView是CDContainerWidget的子类:

class CDContainerView(CDContainerWidget):

class MainFrame:

   def __init__:

     CDContainerView

3). CDContainerWidget 子类 CDContainerView:

class CDContainerWidget(CDContainerView):

class MainFrame:
  def __init__:
     CDContainerWidget

4). 不使用CDContainerWidget和CDContainerView,而是只使用一个名为CDContainerBig的类,该类继承自抽象类View和wxPanel。

class CDContainerBig(View, wxPanel)

我的问题是什么方案是正确的?我已经阅读了MVC模式的维基页面,但是我并不真正理解它的描述,也不知道如何应用它解决我的问题。

嗯,我有一些额外的评论。最初,当我开始设计程序时,我没有考虑太多,只选择了2)方法。但现在,我认为3)方法更好。因为将小部件放入小部件中(将CDContainerWidget放入MainFrame)是合理的。但我不是很确定。此外,使用观察者模式似乎使三个类变得扭曲和笨拙。有时候,我觉得这四个类可能是相同的,只是谁包含谁,或者谁向谁发送消息。嗯,我想我真的需要澄清这一点。

另外,我支持3)是由于一个实际的原因。CDContainerWidget实际上包含几个子小部件组件(按钮,输入框等),如果我们像通过子组件小部件设置新值这样的更改,则对于1),我们需要CDContainerWidget知道CDContainerView,以便让CDContainerView通知其他视图。对于2)来说更糟糕的是,CDContainerWidget必须了解其子CDContainerView。对于3) CDContainerWidget本身就是CDContainerView,因此相当合理。对于4) 嗯,很容易但没有逻辑分离。这是我自己的想法,不知道是否正确。

谢谢!


永远不要在自己的问题下发表评论。请更新您的问题以使其完整。然后,在更新后,请删除混淆的评论。永远不要在自己的问题下发表评论。 - S.Lott
2个回答

1

选项1似乎是最合适的。通常情况下,除非模式需要或有其他强制使用它的原因,否则应避免使用继承。过度使用继承会使您的代码比必要的更紧密集成。


嗨,p-static,谢谢你的回答。你能否详细解释一下为什么1)是最合适的?你所说的只是“委托比继承更好”,没有其他内容,这只是一个通用的设计规则,而不是针对我的问题。老实说,我并不太信服。 - pepero
1
根据我的经验,您不希望在程序的任何其他部分(如View类)中具有GUI代码的依赖关系 - 我在几个项目中都这样做过,但很快就后悔了。因此,这就排除了2)和4)。 3) 实际上似乎是一个合理的解决方案; 我唯一的问题是我对继承的偏见 :) - p-static
你说的每一点都非常正确。与一个无理地想要到处使用继承相比,“反对继承”总是更好的选择。 - Raveline

1

如果你想要减少类之间的耦合,实现信号槽模式可能会让这个过程更容易一些。你可以使用Spiff Signal或其他可用的信号/槽模块。

通过解耦通信逻辑,你可以完全摆脱模块直接交流的需要,而是使用消息传递和回调函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接