DEV Community

Discussion on: Understanding Design Patterns: Null Object

Collapse
jbristow profile image
Jon Bristow

Instead of a Null Object, you should go all-the-way and just use a monoid.

That way you won't have the tonally weird situation described above when you have a NullSaiyan and a Saiyan type in your hierarchy, but you'll gain the benefits of the Null Object Pattern...

To me, seeing a Maybe Saiyan (which can either be a Saiyan or None) makes more contextual sense, as I know this is an object that can be one or the other.

It also allows me to create things like:

/*
 * Adds two Maybe Point objects into a list.
 */
fun Option<Point>.plus(element: Option<Point>) = this.fold(
    ifEmpty = { element.map(::listOf) },
    ifSome = { a ->
        element.fold(
            ifEmpty = { listOf(a) },
            ifSome = { b -> listOf(a, b) }
        ).some()
    }
)

Using a monoid lets you move the definition to the handler functions instead of providing you with a place to hide functionality away to surprise later consumers.

Collapse
drmaquino profile image
Mariano Aquino

The whole idea of the pattern is to let the client not know whether it is dealing with actual objects or nulls. It is usually used with "for-each"s and it is yet another case of polymorphism.
Your idea sounds good if you wanted to let the client decide what to do on each type, which is not the use case of this pattern.
Of course, different scenarios require different approaches.