I recently watched this youtube tutorial on the Null Object design pattern. Even though there were some errors in it: such as the NullCar that doesn't do anything creates an infinite loop, the concept was well explained. My question is, what do you do when the objects that can be null have getters, and are used in your code? How do you know which value to return by default? Or should I implement this pattern inside all the objects? What if I need to return strings or primitives? I'm talking from a Java perspective.
EDIT: won't I be trading null objects testing for default value testing ? If not , why not ?
In object-oriented computer programming, a null object is an object with no referenced value or with defined neutral ("null") behavior. The null object design pattern describes the uses of such objects and their behavior (or lack thereof). Here's the definition of Node interface.
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. an object requires a collaborator.
In Null Object pattern, a null object replaces check of NULL object instance. Instead of putting if check for a null value, Null Object reflects a do nothing relationship. Such Null object can also be used to provide default behaviour in case data is not available.
The null object pattern provides a non-functional object in place of a null reference and therefore allows methods to be called on it. So, for some invalid input to the method GetMobileByName, our MobileRepository would return an instantiated, yet null, IMobile object in place of a null reference.
The objective of a Null Object is to avoid having Null references in the code. The values returned by Null Object getters depend on your domain. Zero or empty string are usually appropriate.
If we transpose the Null Object pattern to real life, what you're asking is similar to ask "how old is nobody ?".
Perhaps your design can be improved as you seem not to follow the tell, don't ask principle.
EDIT: the Null Object design pattern is typically used when an object delegates behavior to another object (such as in Strategy or State Design Patterns) ; as Tom Hawtin - tackline commented, use Special Case Objects for objects returning values.
As far as I've understood it the idea is that the null object's value is as close to "nothing" as possible. That unfortunately means you have to define it yourself. As an example I personally use "" when I can't pass a null String, null object number for me is -1 (mostly because by default most database sequences start at 1 and we use those for item id:s a lot so -1 is dead giveaway it's a null object), with lists/maps/sets it's Collections.EMPTY_SET
, EMPTY_MAP
or EMPTY_LIST
and so on and so forth. If I have custom class I have to create a null object from, I remove all actual data from it and see where that takes me and then apply what I just mentioned until it's "empty".
So you really don't "know" which value to return by default, you just have to decide it by yourself.
what do you do when the objects that can be null have getters , and are used in your code ? How do you know which value to return by default ?
How do you know which classes to implement? This is a design question, it depends on the application.
Generally speaking the purpose of the NullObject pattern is to support a Replace Conditional with Polymorphism refactoring in the special case where the the conditional is a comparison against the null value of the programming language.
A correct implementation of the example in the video would require delegating the driveCar
method to the Car
classes. The SlowCar
and FastCar
classes would perform the loop, presumably through a shared implementation in a base class, and the NullCar
would just return immediately.
In a Java context, the NullCar.speed
attribute would probably be an unboxed int. So setting it to null
is not an option. I would probably hide the attribute behind accessor, and have NullCar.getSpeed
raise an exception. Any client code that would need a test to avoid this exception would instead move into the car classes.
Delegating all operations that directly depend on a speed value being available is an application of the Tell Don't Ask principle of object-oriented design mentioned by philippe
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With