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
用作标记接口。 我不太喜欢这种方法,原因有三个:
- 属性需要标记为虚拟的
- 我无法再密封我的实体类
- 至少引入了 (n+1) 个新类型(n 个空对象,一个标记接口)
为什么不'它是这样实现的:
public class Customer
{
public static readonly Customer NullCustomer = new Customer(){Name = "ImtTheNullCustomer";}
public string Name {get; set;}
}
我通常发现福勒斯的所有例子都经过深思熟虑,显然我在这里错过了一些东西。
Why does Fowler PoEAA p. 498 define the null-object pattern in the following way (sample shortened, language is c# but doesn't matter):
public class Customer
{
public virtual string Name {get; set;}
}
public class NullCustomer : Customer, INull
{
public override Name
{
get { return "ImTheNull";}
// setter ommitted
}
}
INull
is used as a marker interface.
I don't really like this approach for three reasons:
- Properties need to be marked virtual
- I can't seal my entity classes anymore
- At least (n+1) new types are introduced (n null objects, one marker interface)
Why isn't it implemented like this:
public class Customer
{
public static readonly Customer NullCustomer = new Customer(){Name = "ImtTheNullCustomer";}
public string Name {get; set;}
}
I have generally found all of Fowlers examples well thought and there clearly must be something I have missed here.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
继承的原因是为了覆盖类的行为。在我看来,您思考的方式似乎是要检查您拥有的对象是否等于 NullCustomer 静态实例来做出决定,但是 null 对象的要点是坚持里氏替换原则。
换句话说,您使用 null 对象来设置引用,并且不会对其进行特殊检查,您只会使用它,并且它应该具有不同的行为(实际上缺乏行为)。
The reason for the inheritance is to override the behavior of the class. The way you are thinking about it seems to me like you are going to check if the object you have is equal to the
NullCustomer
static instance to make a decision, however the point of the null object is to uphold the Liskov's substitution principle.In other words, you use the null object to set a reference and you will not have a special check for it, you will just use it and it should have a different behavior (really a lack of behavior).
您的第二个示例(具有魔术值)的问题在于,如果您的类具有属于该类的其他项目,那么您现在必须插入针对魔术的检查以决定返回信息或其他一些适当的信息。
对于 Null 类,该类会返回最有意义的内容,而无需进行此类检查。
例如,在适当询问数据库后,客户类别可能会返回该用户的总美元支出。 NullCustomer 只能
返回 0;
。有了这个神奇的值,它要么从数据库中获取虚拟用户的信息,要么必须在做明智的事情之前运行另一个特定的检查。The problem with your second example, with a magic value, is that if your class has other items that are part of the class, you now have to insert checks against the magic to decide to return information, or some other appropriate information.
With a Null class, the class returns what makes most sense without such checks being required.
For example, the customer class might return the total dollar spend by that user, after interrogating the DB as appropriate. A NullCustomer would just be able to
return 0;
. With the magic value, it would either fetch information for a dummy user from the DB, or have to run another specific check before doing the sensible thing.补充一下Chap所说的内容。使用空对象模式以便有一组可接受的默认值。此外,如果您尝试在 MVC 中使用 NullCustomer,您仍然能够访问表示模型的对象,而不必考虑潜在的不存在的数据。 [检查空值]
Adding to what Chap said. The Null Object pattern is used so that there is a default set of values that is acceptable. Additionally, if you attempted to use a NullCustomer within a MVC, you would still be able to access the object representing the model, rather than have to account for potential non-existant data. [checking for nulls]
我不是 C# 程序员,但在第二个示例中,您似乎可以执行以下操作:
一般来说,对象具有行为,而不仅仅是数据,因此它变得更加复杂。
I'm not a C# programmer, but it looks like in your second example that you could do the equivalent of:
In general, objects have behaviour, not just data, so it becomes more complicated.