【问题标题】:What design pattern should I choose for different classes with common ancestor and common descendants?对于具有共同祖先和共同后代的不同类,我应该选择什么设计模式?
【发布时间】:2015-07-14 12:52:10
【问题描述】:

我现在正在重构我的一些代码。我有两个——大部分是多余的——单元,每个产品一个。两者都包含一个继承少数子类的基类。它们也继承了更多的子类。

现在我想合并两个单元,这样冗余代码就不再是冗余的了,不同的部分分别在两个不同的单元中实现。

我首先想到了一些像下面这样的层次结构:

                        BaseClass
                           / \
                          /   \
                         /     \
                        /       \
                       /         \
                      /           \
                     /             \
                    /               \
                   /                 \
                  /                   \
         Product<A>BaseClass   Product<B>BaseClass
                  \                   /
                   \                 /
                    \               /
                     \             /
                      \           /
                       \         /
                        \       /
                         \     /
                          \   /
                           \ /
                            X
                           /|\
                          / | \
                         /  |  \
                        /   |   \
                       /    |    \
                      /     |     \
                     /      |      \
                    /       |       \
                   /        |        \
                  /         |         \
                 /          |          \
                /           |           \
               /            |            \
         SubClass<1>   SubClass<2>   SubClass<3>
             / \                          |
            /   \                         |
           /     \                        |
          /       \                       |
         /         \                      |
        /           \                     |
       /             \                    |
SubClass<1.1>   SubClass<1.2>       SubClass<3.1>

但问题是X,继承在特定于产品的类下连接,因为这种继承在 Delphi 语言中是不可能的。

那么,我认为必须有一种设计模式,它对实现具有公共父类和公共后代类的模型很有用?


编辑:我制作了一个 UML 类图来阐明当前情况。

【问题讨论】:

  • 你可以用接口构建它。
  • @TLama 但是我该如何实现代码呢?接口应该是什么?所有类(除了那些产品类)确实已经存在。
  • 就像 TLama 所说,使用接口并将通用功能委托给自己的类。在您的 BaseClass 和后代中使用这些类。 Favor composition over inheritance
  • 什么是 X?类设计的“钻石”形状经常导致混乱。为什么不将Product&lt;A&gt;BaseClass Product&lt;A&gt;BaseClass 放在一起(一个类),或者如果它们应该分开,有单独的子类?至于模式,您是否将delegation via interfaces 视为一种模式,而不是正常的多态性?这允许您拥有一组具有相同接口的类,您不必重写实现,因为您委托给另一个(共享)类。
  • 这就是将继承作为重用代码和删除重复的机制的问题。它忽略了重用代码的最自然方式,即:简单地使用其他对象。您几乎可以肯定有一个问题,因为您当前的对象正在做“太多”。将通用功能提取到单独的类中。 (注意:其他人建议的 interface 不是必需的,但在某些情况下它们可能很有用。)

标签: delphi oop design-patterns refactoring


【解决方案1】:

现在我想合并两个单元,这样冗余代码就不再是冗余的了,不同的部分分别在两个不同的单元中实现。

如果 ABBaseClass 下降并且每个都有 something 共同点(你的 X),那么你应该意识到 something 应该是BaseClass 的一部分。这就是你的解决方案,它真的就这么简单。

如果 AB 将执行委托给外部代码(带有事件、回调例程等),而这些代码在不知不觉中恰好是相同的代码,那很好。

【讨论】:

    【解决方案2】:

    没有看到你的实际课程,也不知道你想要达到什么目标,很难给出答案,因为有很多考虑因素。

    像 C++ 这样的真正多重继承是不可能的。您可以对接口执行类似的操作,但在这里似乎不合适,因为您没有指出任何类仅从 A 或 B 派生,因此如果您实现它们,则无论如何都必须将所有实际函数定义移动到 X。

    但是 X 是什么?从逻辑上考虑。如果 A 是水果,B 是圆形,X 是橙子,那么正如 NGLN 所说,您需要将 A 和 B 合并到 X(或 BaseClass)中,然后将 A 和 B 扔掉。

    另一方面,如果 A 是汽油箱、B 前照灯和 X 车,那么 X 将包含两个类成员 A 和 B,并且子类将引用这些成员。

    另一方面,如果实际上存在仅从 A 和 B 派生的类,那么您可以选择使用接口并接受这样一个事实,即某些实现可能必须在 A 的后代中复制(并且在 B 中单独复制)在 X 中,或者,也许等效地,从基类派生 X 并在 X 中复制 B 和 C 的函数。最后两个选项都不是理想的,你可以选择合并它们并从 X 派生所有东西,不管它是否真的来自 A 或 B。

    【讨论】:

      【解决方案3】:

      我将详细说明NGLN 在他的回答中解释的内容,因为考虑到您提供的信息,它似乎是最好的。

      考虑以下类模型作为您可能的解决方案:

      TProduct = class
        // Declarations for any product
      end;
      
      TProductA = class(TProduct)
       // Declarations for any products of kind A
      end;
      
      TProductB = class(TProduct)
        // Declarations for any products of kind B
      end;
      
      TProductA1 = class(TProduct)
        // Declarations for product A1
      end;
      
      TProductA2 = class(TProduct)
        // Declarations for product A2
      end;
      
      TProductB1 = class(TProduct)
        // Declarations for product B1
      end;
      
      // Other product declarations
      

      除非您有其他复杂的情况,否则这似乎是您所需要的!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-12-24
        • 1970-01-01
        • 1970-01-01
        • 2014-05-24
        • 1970-01-01
        • 2020-03-04
        • 1970-01-01
        相关资源
        最近更新 更多