【问题标题】:Aren't there any better ways of displaying an object other than using hierarchy?除了使用层次结构之外,没有更好的方法来显示对象吗?
【发布时间】:2008-10-09 10:18:15
【问题描述】:

我有一个这样的类层次结构:

        +-- VirtualNode
        |
INode --+                  +-- SiteNode
        |                  |
        +-- AbstractNode --+
                           |
                           +-- SiteSubNode

还有一个基于INode 的相应NodeCollection 类。为了显示NodeCollection,我需要知道每个成员的最终类型。所以我需要这样的功能

foreach (INode n in myNodeCollection)
{
    switch(n.GetType())
    {
        case(typeof(SiteNode)):
        // Display n as SiteNode
    }
}

现在,这实际上不是一种面向对象的方式。 您认为是否有任何模式或推荐的方法来做同样的事情?

编辑
我已经想过在 INode 接口中添加一个DisplayRender 方法。这具有将视图与模型耦合的副作用,我真的很想避免这种情况。

【问题讨论】:

    标签: c# design-patterns


    【解决方案1】:

    我想你要的是visitor pattern

    【讨论】:

    • 也许吧。我只使用过传统的访问者模式。不过,我肯定会花时间研究这个。
    【解决方案2】:

    Polymorphism:

    当您有一个使用对象类型的 select 语句时,它是重构为多态性的主要候选者。

    查看 Martin Fowler 的书 Refactoring

    “面向对象代码最明显的症状之一是它相对缺乏开关(或 案例)陈述。 switch 语句的问题本质上是重复问题。经常你 找到分散在不同地方的程序的相同 switch 语句。如果你添加一个新的 子句到 switch,你必须找到所有这些 switch、语句并更改它们。面向对象的 多态性的概念为您提供了一种优雅的方式来处理这个问题。

    大多数情况下,您应该考虑多态性的 switch 语句。问题是在哪里 应该发生多态性。 switch 语句通常会打开类型代码。你要 承载类型代码值的方法或类。所以使用Extract Method来提取开关 语句,然后 Move Method 将其放到需要多态性的类中。在 那一点你必须决定是用子类替换类型代码还是替换 带有状态/策略的类型代码。设置好继承结构后,可以使用 用多态替换条件。”

    这是在您的情况下使用多态性的一种方法:

    1. 在 AbstractNode 命名为 显示()。

    2. 然后在里面实际实现Display() 每个 SiteNode 和 SiteSubNode 类。

    3. 然后,当你需要显示这些 节点,你可以简单地迭代 通过一个包含 AbstractNode 类型的项目和调用 Display() 为每个。

    4. 对 Display() 的调用将 自动解析为实际 实际的具体实施 该项目的类型。

    5. 注意:您也可以移动 来自 AbstractNode 的 Display() 方法 到 INode 接口,如果 VirtualNode 将被显示。

    【讨论】:

    • 我不想这样做,因为它会将视图与模型耦合!
    • 怎么样?您的示例中哪些类是视图,哪些是模型?您是否意识到,仅通过使用继承,您就可以自动将子类耦合到父类?多态与否。
    • 就像我说的,使用访客模式。定义一个 INodeVisitor 接口并创建一个实现该接口的 NodeDisplayer 类。使用访问者模式将节点层次结构与引用节点的类分离。
    • Andrew,为简单起见,在每个类中都有一个 Display() 方法仍然是完全可行的方法。 Display() 仍然可以很高兴地委托给其他一些面向 UI 的对象。访问者模式在更简单的情况下是多余的。
    【解决方案3】:

    如果您可以更改 INode 接口 - 添加一个返回“视图”的虚拟方法并在继承的类中覆盖它。

    如果您无法更改基本接口 - 为每个类实现扩展方法并让它们返回每个特定类的“视图”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-15
      • 1970-01-01
      • 1970-01-01
      • 2011-08-28
      相关资源
      最近更新 更多