我想分享一些我的想法和问一些问题Null对象设计模式应该实现具有中立行为的类。所以,如果我需要实现接口:
public interface IProduct
{
double Cost();
string Name();
}
可能,我将使用下一个实现:
public class NullProduct : IProduct
{
public double Cost()
{
return 0.0;
}
public string Name()
{
return String.Empty;
}
}
。
但是,当我需要实现下一个接口时,我应该使用哪种策略:
public interface IProduct
{
//other methods...
bool IsTasty();
}
IsTasty -没有"中立"的行为。我应该如何实现它在NullProduct类?返回真或假。不清楚。
更糟糕的是,如果接口有一些属性:
public interface IProduct
{
//other methods...
int Price{get;set;}
}
和实现:
public class NullProduct : IProduct
{
//other methods...
int Price
{
get {return 0;}
set {/*nothing*/}
}
}
为什么?因为,如果某个用户会得到这个对象,比如这里:
IProduct prod = GetSomeObject(); //GetSomeObject returns NullProduct
和user try do:
prod.Price = 8;
Console.WriteLine(prod.Price);
用户将得到奇怪的结果。用户记得,他买了8元的价格,但现在价格得0。通货膨胀?
在UnitTest中同样的问题
现在,我不想通过询问对象是否是null对象来违反OCP。
你如何解决这个问题?
如果您没有"中性"返回结果,您应该"发明"一个,并在null对象中使用它:
enum Tasty {
Yes, No, Unknown
}
public interface IProduct {
Tasty IsTasty();
}
写入一个空对象几乎不可避免地是一个编程错误,所以Price
的实现应该像这样:
public class NullProduct : IProduct {
//other methods...
int Price {
get {return 0;}
set { throw new InvalidOperationException(); }
}
}
可以将NullObject设计模式"完全组件化"为一个通用的可重用实现,因此您无需担心在每种情况下处理所有可能的细节(只要您需要Nullify的是接口类型)。注意,它还将处理接口函数返回另一个用户定义类型的情况。在这种情况下,它将创建另一个NullObject实例并返回它,因此您将获得一致的深层NullObject实例。
这是一个通用的可重用实现nullobject。java在这里你可以看到它是如何使用的testnullobject。java