docs: update null object

This commit is contained in:
Ilkka Seppälä
2024-05-26 15:38:04 +03:00
parent 1e2dbf2b9b
commit 42db186033
+11 -22
View File
@@ -19,9 +19,11 @@ To provide a default behavior for an object, avoiding the need for null checks a
## Explanation
Real world example
Real-world example
> We are building a binary tree from nodes. There are ordinary nodes and "empty" nodes. Traversing the tree normally should not cause errors, so we use null object pattern where necessary.
> A real-world analogy for the Null Object pattern can be found in the context of customer service. Imagine a customer service system where there are different types of support representatives: human agents and automated bots. When a customer request is received, the system can assign it to a human agent or, if no agents are available, to an automated bot. If neither human agents nor automated bots are available, the system assigns the request to a "Null Representative."
>
> The Null Representative is a placeholder that does nothing but ensures that the system doesn't crash or raise errors due to the absence of a support representative. It provides default responses like "Your request is being processed" without any actual processing, thereby maintaining system stability and avoiding the need for null checks throughout the codebase.
In plain words
@@ -33,6 +35,8 @@ Wikipedia says
**Programmatic Example**
We are building a binary tree from nodes. There are ordinary nodes and "empty" nodes. Traversing the tree normally should not cause errors, so we use null object pattern where necessary.
Here's the definition of `Node` interface.
```java
@@ -60,9 +64,6 @@ public class NodeImpl implements Node {
private final Node left;
private final Node right;
/**
* Constructor.
*/
public NodeImpl(String name, Node left, Node right) {
this.name = name;
this.left = left;
@@ -142,17 +143,9 @@ public final class NullNode implements Node {
Then we can construct and traverse the binary tree without errors as follows.
```java
var root = new NodeImpl("1",
new NodeImpl("11",
new NodeImpl("111", NullNode.getInstance(), NullNode.getInstance()),
NullNode.getInstance()
),
new NodeImpl("12",
NullNode.getInstance(),
new NodeImpl("122", NullNode.getInstance(), NullNode.getInstance())
)
);
root.walk();
var root = new NodeImpl("1", new NodeImpl("11", new NodeImpl("111", NullNode.getInstance(), NullNode.getInstance()), NullNode.getInstance()),
new NodeImpl("12", NullNode.getInstance(), new NodeImpl("122", NullNode.getInstance(), NullNode.getInstance())));
root.walk();
```
Program output:
@@ -165,10 +158,6 @@ Program output:
122
```
## Class diagram
![Null Object](./etc/null-object.png "Null Object")
## Applicability
* When you need to provide a default behavior in place of a null object.
@@ -202,8 +191,8 @@ Trade-offs:
## Credits
* [Pattern Languages of Program Design 3](https://www.amazon.com/gp/product/0201310112/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201310112&linkCode=as2&tag=javadesignpat-20&linkId=7372ffb8a4e39a3bb10f199b89aef921)
* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)
* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)
* [Effective Java](https://amzn.to/4cGk2Jz)
* [Pattern Languages of Program Design 3](https://amzn.to/3UZkRF6)
* [Refactoring to Patterns](https://amzn.to/3VOO4F5)
* [Refactoring: Improving the Design of Existing Code](https://amzn.to/3UJ7etA)