我想分享我的一些想法并提出一些问题 空对象设计模式应该实现具有中性行为的类。 所以,如果我需要实现接口:
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类中实现它?返回true或false。不太清楚。
更糟糕的是,如果界面有一些属性:
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
并且用户尝试执行:
prod.Price = 8;
Console.WriteLine(prod.Price);
用户会得到奇怪的结果。用户记得,他支付8美元的价格,但现在价格得到0.通货膨胀?
在UnitTest中遇到同样的问题。
现在,我不想通过询问对象是否为null对象来违反OCP。
你如何解决这个问题?
答案 0 :(得分:2)
如果你没有“中性”返回结果,你应该“发明”一个,并在空对象中使用它:
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(); }
}
}
答案 1 :(得分:0)
可以将NullObject设计模式“完全组件化”为通用的可重用实现,这样您就不必担心在每种情况下处理所有可能的细节(只要您需要的话) Nullify是一种接口类型)。请注意,它还将处理您的接口函数返回另一个用户定义类型的情况。在这种情况下,它将创建另一个NullObject实例并返回它,因此您可以一致地获得深层NullObject实例。
这是一个通用的可重用实现NullObject.java,您可以在此处查看如何使用TestNullObject.java