2009-11-10 45 views
4

为什么福勒PoEAA p。 498定义以下面的方式在空物体图案(样品缩短,语言是C#,但没关系):Fowler空对象模式:为什么使用继承?

public class Customer 
{ 
    public virtual string Name {get; set;} 
} 

public class NullCustomer : Customer, INull 
{ 
    public override Name 
    { 
    get { return "ImTheNull";} 
    // setter ommitted 
    } 
} 

INull被用作一个标记接口。 我真的不喜欢这种方法的原因有三:

  1. 属性需要标记虚拟
  2. 我不能封我的实体类了
  3. 至少(N + 1)的新类型介绍(N空对象,一个标记接口)

为什么不是实现这样的:

public class Customer 
{ 
    public static readonly Customer NullCustomer = new Customer(){Name = "ImtTheNullCustomer";} 

    public string Name {get; set;} 
} 

我一般都会发现所有Fowlers的例子都很好想,显然必须有一些我在这里错过的东西。

+0

请勿使虚拟方法变为虚方法,或者因为这个原因让类不启动。虽然我非常尊重Martin Fowler,但他的许多涉及继承的例子都存在明确的Java偏见。在Java方法中默认是虚拟的。在C#中,他们不是,并且设计决定是由于默认虚拟方法的问题而产生的。无论如何,如果NullCustomer将成为有效的客户,请使用此模式。一个很好的指标是将其与空列表进行比较。一个空的列表是一个非常好的列表,宣传它并没有什么坏处。这可能不是这种情况。 – 2016-06-26 06:21:39

回答

10

继承的原因是重写类的行为。你对我的想法似乎就像你要检查你所拥有的对象是否等于NullCustomer静态实例来做决定,然而空对象的要点是支持Liskov's substitution principle

换句话说,你使用空对象来设置引用,你不会有特殊的检查,你只会使用它,它应该有不同的行为(真的缺乏行为)。

+0

您在Liskov的名字中输入了错字。 – 2009-11-10 19:25:51

+0

好的,所以问题是关于方法(计算等),而不是简单的获取设置属性? (与Alister同样的问题) – 2009-11-10 21:23:10

+1

是的行为是在方法甚至属性。注意在你的例子中,setter在空对象中缺失。这改变了基类中的行为,其中null对象是只读的。 – Chap 2009-11-10 21:35:39

1

你的第二个例子有一个魔法值的问题是,如果你的类有其他项目是类的一部分,你现在必须插入检查魔法来决定返回信息或其他适当的信息。

使用Null类,类将返回最有意义的内容,而无需进行此类检查。

例如,在询问数据库后,客户类可能会返回该用户的总美元支出。 NullCustomer将仅能够return 0;。有了魔法值,它会从数据库中获取虚拟用户的信息,或者在做出明智的事情之前必须运行另一个特定的检查。

+0

好吧,所以问题是关于方法(计算等),而不是简单的获取设置属性。 – 2009-11-10 18:35:49

+0

0是否为正确的默认值?这取决于你想要做什么。您不希望将NullCustomer插入到您的数据库中... – 2016-06-26 06:25:24

0

加入Chap所说的内容。使用Null对象模式,以便有一组默认的值是可接受的。此外,如果您尝试在MVC中使用NullCustomer,则仍然可以访问代表模型的对象,而不必考虑潜在的不存在的数据。 [检查空]

0

我不是一个C#程序员,但它看起来像你的第二个例子,你可以做相当于:

Customer.NullCustomer.Name = "Not Null"; 

一般而言,对象具有的行为,而不仅仅是数据,所以它变得更加复杂。

+0

是的,你有这个权利,其他人已经提到,但已经。无论如何感谢您的评论。 – 2009-11-10 21:22:39