空对象设计模式与行为有关

时间:2012-12-26 06:47:57

标签: design-patterns null-object-pattern

我想分享我的一些想法并提出一些问题 空对象设计模式应该实现具有中性行为的类。 所以,如果我需要实现接口:

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。

你如何解决这个问题?

2 个答案:

答案 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