2016-09-20 116 views
1

我无法确定下面这两个示例的优点和缺点。理想情况下,我想知道它的重量高达最佳的设计方案:空派生类与Vs类型属性

例1(类型属性):

public abstract class Animal : /* all relevant interfaces*/ 
{ 
    /* 
    All necessary implementations 
    */ 
} 

Public class Dog : Animal 
{ 
    Public string Name {get; set;} 
    Public Breed Type {get; set;} 

    /* 
    All necessary implementations 
    */ 
} 

Public Type Breed 
{ 
    Bulldog, 
    Chihuahua, 
    Labrador, 
    /* 
    So on…… 
    This can grow without limitation, 
    you dno't know how much it will grow into, or 
    what breed you will have tomorrow e.g BulldogChihuahuaCross, 
    or BulldogLabradorCross. 
    */ 
} 

例2(空派生类):

public abstract class Animal : /* all relevant interfaces*/ 
{ 
    /* 
    All necessary implementations 
    */ 
} 

Public class Dog : Animal 
{ 
    Public string Name {get; set;} 

    /* 
    All necessary implementations 
    */ 
} 

Public class Bulldog : Dog 
{ 
    /* Empty Class */ 
} 

Public class Chihuahua: Dog 
{ 
    /* Empty Class */ 
} 

Public class Labrador: Dog 
{ 
    /* Empty Class */ 
} 

编辑:

在示例1创建Dog的实例,并将其类型指定为属性,在示例2中创建该特定类型的实例。

我正在寻找一些深入的论点,可扩展性,可维护性,在CPU上的成本,如果有1000种品种,运行查询等费用。

+0

这实际上是一个非常好的问题,大多数人都懒得问。我认为对你来说,这是一个很好的答案,但是直到今天晚些时候,你才没有时间写出来。敬请关注。 –

+0

@ JimL.I期待着您的回答。 – Jegan

+0

@JimL。或者像费马特说:我有一个很好的证据,但这里的边际太窄了,不能写下来;-) –

回答

2

频谱有两种极端情况。一方面是那些仅仅是信息化的东西,并被操作为文本,数字或对枚举实例的引用。例如,一个狗沙龙应用程序可能会记录您的宠物的名称,颜色和品种,仅作为识别目的的文本。另一方面是一些需要具有不同属性,操作或方法的东西。例如,视频游戏可能会在每次发出吠声时为每只狗发出不同的声音。

作为设计师必须做出的决定是如何准确地反映“话语的领域”与何时采取特定应用的快捷方式。在话语领域,每个品种都具有独特的特征,但对于狗沙龙应用的目的而言,你根本不在意。在这种情况下,您可以设计出细节,并希望将来您永远不需要它。

问题出在该频谱的中间,在那里有人做出错误的决定。我曾在大型企业系统上工作过,在那里有人将继承层次压缩成显式编码为一个或多个数据库列中值的类型。这很可怕,因为它成为程序员的问题,知道哪些其他列对于每种编码类型都是有效的。该系统在各地都有切换语句,以实施随时间演变成非常复杂的业务规则。该系统有很多错误。

因为这个原因,在光谱中间的地方,事情并不那么清晰,我会在许多课堂上犯错。理由是准确地反映域使得更容易判断是否满足要求,并且可以使代码更直观地维护(假设它是DDD)。反映域的关键是准确地表示事物集合。例如,“Fido”是Dog集合和Animal超集的成员; “西尔维斯特”是猫组和动物超集的成员。这对于人们来说很容易理解,并且每个类都可以有不同的外部隐藏的实现。一旦你开始解释显式编码为字符串,整数或枚举类型引用的类型,你就需要遍布各处的switch语句,并且你有一个难以维护,难以理解的混乱。许多面向对象的语言可以为您节省所有这些,但您必须创建一个包含完整类型列表的工厂。运行时开销可以忽略不计(特别是如果您实现工厂在恒定时间运行),并且类型可以映射到关系数据库中的值,以便您可以查询并报告它们。此外,正如您所指出的,您可能会利用仿制药。

如果你知道你的课程将永远是空的,就像在一个狗沙龙应用程序的情况下,不要打扰类。如果您知道他们将拥有不同的属性,操作和方法,或者如果您不确定,请使用类。

+0

谢谢吉姆。这正是我的问题,我给出的例子比我现实中的要简单得多。我正在研究一个非常复杂的企业系统。它使用“事件源”和DAG(有向无环图),因此系统有两部分,第一部分创建对象的实例,第二部分,这些对象注册了依赖大量使用泛型的事件源。为了适应泛型的使用,随着时间的推移,空的类已经接管了。 – Jegan

+0

虽然在项目开始的时候,有很多未知的,但现在,它有点解决。我的问题是值得从话语领域转移,同时我希望保持谨慎,不要像开关语句或任何地方那样在大混乱中结束。 – Jegan

+0

为什么现在要改用枚举的机会呢?我指出了在这条道路上肮脏的可能性。我不认为班级有一个真正的缺点,除了他们很烦人。 –

1

第一种方法可以让你确定哪些品种是狗,但第二种方法可以让你为子类制定特定的实现。

如果您打算需要对象为每个不同的狗品种设置不同的方法或属性,请使用派生类,否则仅更简单地使用类型属性和单个类。

+0

我正在寻找一个深入探讨两个设计的利弊的论点;比如说,这是一个拥有100万只狗和1000个品种的企业系统。 – Jegan

+1

用户Kasper Holdum已经有相当长的讨论:[http://stackoverflow.com/questions/1338391/when-to-subclass-instead-of-differentiating-the-behaviour](http://stackoverflow。 com/questions/1338391/when-to-subclass-instead-of-differentiating-the-behavior) – SilentLupin

+1

实际上,这与你的问题几乎完全相同,并且回答得很好:[http://stackoverflow.com/questions/4254182 /inheritance-vs-enum-properties-in-the-domain-model](http://stackoverflow.com/questions/4254182/inheritance-vs-enum-properties-in-the-domain-model) – SilentLupin

1

好吧,这里是我的2美分:如果你正在寻找一个快速访问任何东西,你会把它放在一个关联数组中。你的两个实现都提供了一个哈希码来作为对象地址,这使得它们可以以相同的速度访问。只有打算添加功能时,子类才有意义(基本上)。从枚举中获取类型与从枚举中获取类型没有什么不同。如果你需要聪明的查询,创建一个聪明的关联数组。

+0

这是一个很好的观点。我试图从空的子类移动到类型列表,但我想确保我不会在设计中创建混乱。 – Jegan

+0

设计方面(如上所述)枚举是更好的选择,因为您只创建用于输入的子类而不添加功能,这是他们的真正目的。 –