【问题标题】:To subclass or not to subclass子类化或不子类化
【发布时间】:2010-12-30 19:33:33
【问题描述】:

我有三个对象;行动、问题和风险。这些都包含许多常见变量/属性(例如:描述、标题、到期日、提出者等)和一些特定字段(风险有概率)。问题是:

  1. 我应该创建 3 个单独的 类 Action、Risk 和 Issue 各 包含重复字段。

  2. 创建父类“Abstract_Item” 包含这些字段和 对它们进行操作,然后有 行动、风险和问题子类 Abstract_Item。这将坚持 DRY 原则。

【问题讨论】:

    标签: oop subclass


    【解决方案1】:

    我的观点

    假设你使用了继承。在一段时间内,您拥有只有 ActionIssue 而不是 Risk 共有的新属性。你将如何处理这件事?如果您将它们放在 parent 之下,那么 Risk 正在继承无关紧要的东西(Liskov Substituon 原则敲门?)。如果您将 then 分别放在 Action 和 Risk 中,那么您将破坏 DRY,这是您开始继承的最初原因。重点是重用的继承性不好。如果没有“is-a”,那么最好不要使用它,当您有疑问时,就没有真正的“is-a”。

    我的偏好

    还有其他实现 DRY 的方法,如下面的示例代码所示。随着新属性的添加,我将成为另一个Common2,如果新行为不适用于所有 3 个类,则添加新行为是新的CommonBehavior2;如果它们是那么只需更改现有的 CommonCommonBehavior

    public class Common implements CommonBehavior
    {
        String Description;
        String title;
    
        public void f() {}
    }
    
    public interface CommonBehavior
    {
        void f();
    }
    
    public class Action implements CommonBehavior
    {
        private Common delegate;
    
        public void f()
        {
            delegate.f();
        }
    }
    

    另请参阅我对类似问题的回答以及另一个实际示例Design pattern to add a new class

    【讨论】:

    • 感谢您的委托和良好的演示。反过来你怎么看(见下文,任务 -> 主题)。问题是,“截止日期”真的是 Action(您的委托)的一部分,还是工作流的工件,它确实在处理 Action 中发挥作用,仅在工作流上下文嵌入中发挥作用。
    • 感谢您如此清晰地展示 Delegate。我所拥有的行动、问题和风险确实是一组常见的行为。在阅读代码开头时,使用委托方法将使类的工作更加清晰。以下面的“任务”为例,行动可能是一项任务,但风险不是。类的意图变得非常清楚,因为 Action 现在是:“Action 实现 CommonBehaviour、Task、MeetingIem”,其中 Risk 是:“Risk 实现 CommonBehaviour、MeetingItem”。
    • 很高兴您能理解。我建议您也在这里查看我对类似问题的回复stackoverflow.com/questions/4512184/…
    【解决方案2】:

    是的,坚持 DRY 通常是一个非常好的主意除了,如果这些类有非常非常不同的用途(即苹果和汽车都可能是红色的,但我不会同时派生它们)来自名为ProbablyRed 的基类)。但是,在您的情况下,我肯定会选择基类,因为您描述的实现(ActionIssueRisk)似乎都是某种具有非常相似语义的业务规则。

    【讨论】:

      【解决方案3】:

      您似乎正在自己回答这个问题。正如你所说,DRY。

      【讨论】:

        【解决方案4】:

        抽象父类听起来像是要走的路。它还将使可能或更容易(取决于您的语言)实现和使用作用于这三个项目中的任何一个的功能。例如,您可以有一个“获取 {user} 提出的所有项目的列表”函数。

        【讨论】:

          【解决方案5】:

          如果您查看用例,可能会看到另一个方面,可能处理不同的属性子组。

          例如,如果在类似待办事项的应用程序中使用“标签”、“到期日”和“已提出”,并且在处理该任务时会普遍使用“操作”和“风险”的其他属性,您可能会考虑聚合让我们说任务(标签,截止日期,...)和主题,它是对动作、问题或某天会出现的事物的多态引用

          【讨论】:

            【解决方案6】:

            我想我在这里回答了同样的问题

            When to create a class vs setting a boolean flag?

            【讨论】:

              【解决方案7】:

              不要仅仅因为对象共享某些数据或操作而进行子类化。将组合视为遵循 DRY 的默认方式。

              在您的特定情况下,仅当您的对象实际上相关时才创建父类,即与父类存在语义“是”关系。例如,如果 Action、Issue 和 Risk 都是 Ticket 对象。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-12-30
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2010-12-23
                相关资源
                最近更新 更多