سؤال

I want share some of my thoughts and ask some questions Null object design pattern supposed to implement class with neutral behavior. So, if i need implement interface:

public interface IProduct 
{
    double Cost();
    string Name();
}

probably, i will use next implementation:

public class NullProduct : IProduct
{
    public double Cost()
    {
        return 0.0;
    }

    public string Name()
    {
        return String.Empty;
    }
}

Fine.

But, which strategy shall i use, when i need implement next interface:

public interface IProduct 
{
    //other methods...
    bool IsTasty();
}

IsTasty - there no "neutral" behavior. How should i implement it in NullProduct class? Return true or false. No so clear.

Worse, if interface have some properties:

public interface IProduct 
{
    //other methods...
    int Price{get;set;}
}

and implementation:

public class NullProduct : IProduct 
{
    //other methods...
    int Price
    {
        get {return 0;}
        set {/*nothing*/}
    }
}

Why? Because of, if some user will get the object, like here:

    IProduct prod = GetSomeObject(); //GetSomeObject returns NullProduct 

and user try do:

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

user will get strange result. User remembers, he stets 8 dollar price, but now price get 0. Inflation?

In UnitTest same problem.

Now, i do not want violate OCP by asking object if it null object.

How do you solve the problem?

هل كانت مفيدة؟

المحلول

If you do not have a "neutral" return result, you should "invent" one, and use it in the null object:

enum Tasty {
    Yes, No, Unknown
}

public interface IProduct {
    Tasty IsTasty();
}

Writing to a null object is nearly inevitably a programming error, so the implementation of Price should go like this:

public class NullProduct : IProduct {
    //other methods...
    int Price {
        get {return 0;}
        set { throw new InvalidOperationException(); }
    }
}

نصائح أخرى

It is possible to "fully componentize" the NullObject design pattern into a generic reusable implementation so you don't need to worry about handling all possible details in each case (as long as what you need to Nullify is an interface type). Note that it will also handle the case where your interface function returns another User Defined Type. In this case it will create another NullObject instance and return it, so you get deep NullObject instances consistently.

This is a generic reusable implementation NullObject.java and here you can see how it can be used TestNullObject.java

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top