Nazgul
Nazgul

Reputation: 83

Ways to implement Null Object Pattern

Till now I have seen everywhere that the steps to create Null Object Pattern, for example in BST to remove null checks, are as follows:

  1. Create an interface Node

  2. Create two classes implementing the interface Node. One of which will be real_Node and other will be null_Node.

  3. Using those classes, null checks can be removed in BST class while creating the tree.

Now I want to know that, are there other ways to do this, e.g., Can we implement Null Object Pattern without interface using only classes, i.e. in the above step (1.) can we use Node class instead of Node interface

Upvotes: 2

Views: 1940

Answers (1)

sisyphus
sisyphus

Reputation: 6392

Yes, there are ways to implement the Null object pattern without explicitly using a Java interface. However, you are really doing much the same thing so YMMV. You might find problems if you don't have access to the base class and/or it doesn't allow for some form of extending/overriding.

  • Create a class which extends your base class but which does the 'null' operations by overriding them. You would generally hide it behind some kind of static constructor for ease of access.

    class Base {
        public void someMethod() {
            // this stuff does the non-null behaviour
        }
    
        public static Base nullVersion() {
            return new NullOfBase();
        }
    
        private static class NullOfBase extends Base {
            @Override
            public void someMethod() {
               // this guy does the null version.
            }
        }
    }
    
  • Use an anonymous class on a static 'NULL' class member, which overrides the various operations you need to override.

    public class Base {
       public static final Base NULL = new Base() {
            @Override
            public void someMethod() {
               // this guy does the null version.
            }
        }
    
        public void someMethod() {
            // this stuff does the non-null behaviour
        } 
    }
    
  • Use an abstract class to hold the operations which are common to both the non-null and null implementations, marking those methods as final, all other methods are abstract and implemented in two concrete classes - one for the non-null functionality and another for the null functionality. You might use static constructors to keep common use cases easy to construct and concrete class names hidden from view.

    public abstract class Base {
         public final sayHello() {
             System.out.println("Hello world");
         }
    
         public abstract void someMethod();
    
         public static Base nonNullVersion() {
             return new NonNullBase();
         }
    
         public static Base nullVersion() {
             return new NullBase();
         }
    
         private static final class NonNullBase extends Base {
            @Override
            public void someMethod() {
                // this stuff does the non-null behaviour
            }
         }
    
         private static final class NullBase extends Base {
            @Override
            public void someMethod() {
                // this stuff does the null behaviour
            }
         }
    }
    

Alternatively, sometimes a NULL-object is really just a special case of a particular value (it really depends on what the operations on the class are). In that case you could either have a static member with that value or a static factory which allows you to create it.

Upvotes: 3

Related Questions