Java 中的空对象模式:使用优雅的默认值简化错误处理
大约 3 分钟
也称为
- 活动空对象
- 存根
空对象设计模式的意图
空对象模式是 Java 中一个重要的设计模式,它提供了一种无缝的方式来处理不存在的对象,而无需执行空检查,从而简化了 Java 应用程序。
空对象模式的详细解释以及现实世界中的示例
现实世界中的示例
在客户服务领域,我们可以找到空对象模式的一个现实世界中的类比。想象一个客户服务系统,其中有不同类型的支持代表:人工代理和自动机器人。当收到客户请求时,系统可以将其分配给人工代理,或者如果代理不可用,则分配给自动机器人。如果人工代理和自动机器人都不可用,则系统将请求分配给“空代表”。
空代表是一个占位符,它什么都不做,但确保系统不会因为没有支持代表而崩溃或引发错误。它提供默认的响应,例如“您的请求正在处理中”,而无需进行任何实际处理,从而保持系统稳定并避免在整个代码库中进行空检查。
通俗地说
空对象模式优雅地处理“空”对象。
维基百科说
在面向对象的计算机编程中,空对象是一个没有引用值或具有定义的“空”行为的对象。空对象设计模式描述了此类对象的用法及其行为(或缺乏行为)。
Java 中空对象的编程示例
通过实现空对象模式,Java 开发人员可以确保他们的应用程序更优雅地处理“空”对象,从而提高代码的稳定性和可读性。
我们正在从节点构建二叉树。有普通节点和“空”节点。正常遍历树不应该导致错误,因此我们在必要时使用空对象模式。
以下是 Node
接口的定义。
public interface Node {
String getName();
int getTreeSize();
Node getLeft();
Node getRight();
void walk();
}
我们有两种 Node
的实现。普通实现 NodeImpl
和空节点的 NullNode
。
@Slf4j
public class NodeImpl implements Node {
private final String name;
private final Node left;
private final Node right;
public NodeImpl(String name, Node left, Node right) {
this.name = name;
this.left = left;
this.right = right;
}
@Override
public int getTreeSize() {
return 1 + left.getTreeSize() + right.getTreeSize();
}
@Override
public Node getLeft() {
return left;
}
@Override
public Node getRight() {
return right;
}
@Override
public String getName() {
return name;
}
@Override
public void walk() {
LOGGER.info(name);
if (left.getTreeSize() > 0) {
left.walk();
}
if (right.getTreeSize() > 0) {
right.walk();
}
}
}
public final class NullNode implements Node {
private static final NullNode instance = new NullNode();
private NullNode() {
}
public static NullNode getInstance() {
return instance;
}
@Override
public int getTreeSize() {
return 0;
}
@Override
public Node getLeft() {
return null;
}
@Override
public Node getRight() {
return null;
}
@Override
public String getName() {
return null;
}
@Override
public void walk() {
// Do nothing
}
}
然后,我们可以构建和遍历二叉树,而不会出现错误,如下所示。
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();
程序输出
1
11
111
12
122
何时在 Java 中使用空对象模式
- 当您需要在空对象的位置提供默认行为时。
- 通过消除空检查来简化客户端代码。
- 当默认操作比处理空引用更可取时。
Java 中空对象模式的现实世界应用
- 空对象在日志系统中经常使用,它有助于防止 NullPointerException,使其成为可靠的 Java 软件开发的关键模式。
- 使用 NullIterator 以优雅方式处理空集合的集合。
- GUI 系统,其中 NullComponent 可用于表示什么都不做的组件。
空对象模式的优缺点
优点
- 消除了对空检查的需求,减少了 NullPointerException 的风险。
- 简化了客户端代码并提高了可读性。
- 通过公共接口处理默认行为,从而促进了多态的使用。
缺点
- 可能会引入额外的类,从而可能增加系统的整体复杂性。
- 默认行为可能会掩盖原本会通过显式空处理捕获的潜在问题。