4

为什么 Fowler PoEAA p。498 以以下方式定义空对象模式(示例缩短,语言是 c# 但没关系):

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 的例子都经过深思熟虑,显然我在这里遗漏了一些东西。

4

4 回答 4

10

继承的原因是为了重写类的行为。在我看来,您考虑的方式就像您要检查您拥有的对象是否等于NullCustomer静态实例以做出决定,但是空对象的要点是维护Liskov 的替换原则

换句话说,您使用 null 对象来设置引用并且您不会对其进行特殊检查,您只会使用它并且它应该具有不同的行为(实际上是缺乏行为)。

于 2009-11-10T18:06:49.920 回答
1

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

对于 Null 类,该类返回最有意义的内容,而无需进行此类检查。

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

于 2009-11-10T18:06:16.567 回答
0

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

于 2009-11-10T18:16:40.163 回答
0

我不是 C# 程序员,但在您的第二个示例中,您可以执行以下操作:

Customer.NullCustomer.Name = "Not Null";

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

于 2009-11-10T19:19:26.567 回答