The intent of a Null Object is to encapsulate the absence of an object by providing a substitutable alternative that offers suitable default do nothing behavior. In short, a design where “nothing will come of nothing”
Use the Null Object pattern when
Given that an object reference may be optionally null, and that the result of a null check is to do nothing or use some default value, how can the absence of an object — the presence of a null reference — be treated transparently?
Sometimes a class that requires a collaborator does not need the collaborator to do anything. However, the class wishes to treat a collaborator that does nothing the same way it treats one that actually provides behavior.
Consider for example a simple screen saver which displays balls that move about the screen and have special color effects. This is easily achieved by creating a Ball class to represent the balls and using a Strategy pattern to control the ball’s motion and another Strategy pattern to control the ball’s color.
It would then be trivial to write strategies for many different types of motion and color effects and create balls with any combination of those. However, to start with you want to create the simplest strategies possible to make sure everything is working. And these strategies could also be useful later since you want as strategies as possible strategies.
Now, the simplest strategy would be no strategy. That is do nothing, don’t move and don’t change color. However, the Strategy pattern requires the ball to have objects which implement the strategy interfaces. This is where the Null Object pattern becomes useful.
Simply implement a NullMovementStrategy which doesn’t move the ball and a NullColorStrategy which doesn’t change the ball’s color. Both of these can probably be implemented with essentially no code. All the methods in these classes do “nothing”. They are perfect examples of the Null Object Pattern.
The key to the Null Object pattern is an abstract class that defines the interface for all objects of this type. The Null Object is implemented as a subclass of this abstract class. Because it conforms to the abstract class’ interface, it can be used any place this type of object is needed. As compared to using a special “null” value which doesn’t actually implement the abstract interface and which must constantly be checked for with special code in any object which uses the abstract interface.
It is sometimes thought that Null Objects are over simple and “stupid” but in truth a Null Object always knows exactly what needs to be done without interacting with any other objects. So in truth it is very “smart.”
Client
-
AbstractObject
-
<strong>RealObject</strong>
-
<strong>NullObject</strong>
-
NullObject
class will require pluggable variables so that the client can specify how the null object should do nothing (see the discussion of pluggable adaptors in the Adapter pattern). This may generally be a symptom of the AbstractObject
not having a well defined (semantic) interface. ConcreteStrategy
is a NullObject
. For example, a Controller is a View’s Strategy for handling input, and NoController is the Strategy that ignores all input. Simpliest example ever :)
1: class NullOutputStream extends OutputStream {2: public void write(int b) {3: // Do nothing
4: }5: }6:7: class NullPrintStream extends PrintStream {8: public NullPrintStream() {
9: super(new NullOutputStream());10: }11: }12:13: class Application {
14: private PrintStream debugout;
15: public Application(PrintStream debugout) {
16: this.debugout = debugout;
17: }18:19: public void go() {20: int sum = 0;
21: for (int i = 0; i < 10; i++) {22: sum += i;23: debugout.println("i = " + i);
24: }25: System.out.println("sum = " + sum);
26: }27: }