【发布时间】:2010-12-30 19:33:33
【问题描述】:
我有三个对象;行动、问题和风险。这些都包含许多常见变量/属性(例如:描述、标题、到期日、提出者等)和一些特定字段(风险有概率)。问题是:
我应该创建 3 个单独的 类 Action、Risk 和 Issue 各 包含重复字段。
创建父类“Abstract_Item” 包含这些字段和 对它们进行操作,然后有 行动、风险和问题子类 Abstract_Item。这将坚持 DRY 原则。
【问题讨论】:
我有三个对象;行动、问题和风险。这些都包含许多常见变量/属性(例如:描述、标题、到期日、提出者等)和一些特定字段(风险有概率)。问题是:
我应该创建 3 个单独的 类 Action、Risk 和 Issue 各 包含重复字段。
创建父类“Abstract_Item” 包含这些字段和 对它们进行操作,然后有 行动、风险和问题子类 Abstract_Item。这将坚持 DRY 原则。
【问题讨论】:
我的观点
假设你使用了继承。在一段时间内,您拥有只有 Action 和 Issue 而不是 Risk 共有的新属性。你将如何处理这件事?如果您将它们放在 parent 之下,那么 Risk 正在继承无关紧要的东西(Liskov Substituon 原则敲门?)。如果您将 then 分别放在 Action 和 Risk 中,那么您将破坏 DRY,这是您开始继承的最初原因。重点是重用的继承性不好。如果没有“is-a”,那么最好不要使用它,当您有疑问时,就没有真正的“is-a”。
我的偏好
还有其他实现 DRY 的方法,如下面的示例代码所示。随着新属性的添加,我将成为另一个Common2,如果新行为不适用于所有 3 个类,则添加新行为是新的CommonBehavior2;如果它们是那么只需更改现有的 Common 和 CommonBehavior
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
【讨论】:
是的,坚持 DRY 通常是一个非常好的主意除了,如果这些类有非常非常不同的用途(即苹果和汽车都可能是红色的,但我不会同时派生它们)来自名为ProbablyRed 的基类)。但是,在您的情况下,我肯定会选择基类,因为您描述的实现(Action、Issue、Risk)似乎都是某种具有非常相似语义的业务规则。
【讨论】:
您似乎正在自己回答这个问题。正如你所说,DRY。
【讨论】:
抽象父类听起来像是要走的路。它还将使可能或更容易(取决于您的语言)实现和使用作用于这三个项目中的任何一个的功能。例如,您可以有一个“获取 {user} 提出的所有项目的列表”函数。
【讨论】:
如果您查看用例,可能会看到另一个方面,可能处理不同的属性子组。
例如,如果在类似待办事项的应用程序中使用“标签”、“到期日”和“已提出”,并且在处理该任务时会普遍使用“操作”和“风险”的其他属性,您可能会考虑聚合让我们说任务(标签,截止日期,...)和主题,它是对动作、问题或某天会出现的事物的多态引用
【讨论】:
我想我在这里回答了同样的问题
【讨论】:
不要仅仅因为对象共享某些数据或操作而进行子类化。将组合视为遵循 DRY 的默认方式。
在您的特定情况下,仅当您的对象实际上相关时才创建父类,即与父类存在语义“是”关系。例如,如果 Action、Issue 和 Risk 都是 Ticket 对象。
【讨论】: