1

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

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 

和用户尝试做:

    prod.Price = 8;
    Console.WriteLine(prod.Price);

用户会得到奇怪的结果。用户记得,他设定了 8 美元的价格,但现在价格为 0。通货膨胀?

在 UnitTest 中同样的问题。

现在,我不想通过询问对象是否为空对象来违反 OCP。

你如何解决问题?

4

2 回答 2

2

如果您没有“中性”返回结果,您应该“发明”一个,并在 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(); }
    }
}
于 2012-12-26T06:53:52.110 回答
0

可以将 NullObject 设计模式“完全组件化”为通用的可重用实现,因此您无需担心在每种情况下处理所有可能的细节(只要您需要 Nullify 是一个接口类型)。请注意,它还将处理您的接口函数返回另一个用户定义类型的情况。在这种情况下,它将创建另一个 NullObject 实例并返回它,因此您可以获得一致的深层 NullObject 实例。

这是一个通用的可重用实现NullObject.java,在这里您可以看到如何使用它TestNullObject.java

于 2012-12-26T17:04:20.200 回答