目录
意图
Null Object 的目的是通过提供可替代的替代方案来封装对象的缺失,该替代方案提供合适的默认不做任何行为。简而言之,“一无所有”的设计
在以下情况下使用空对象模式
- 一个对象需要一个合作者。Null Object 模式没有引入这种协作——它利用了已经存在的协作
- 一些协作者实例应该什么都不做
- 您想将 null 的处理从客户端抽象出来
问题
假设一个对象引用可以是可选的 null,并且 null 检查的结果是什么都不做或使用一些默认值,那么如何透明地处理对象的缺失——null 引用的存在?
讨论
有时,需要协作者的类不需要协作者做任何事情。但是,该类希望以对待实际提供行为的协作者相同的方式对待不做任何事情的协作者。
例如,考虑一个简单的屏幕保护程序,它显示在屏幕上移动并具有特殊颜色效果的球。这很容易实现,方法是创建一个 Ball 类来表示球并使用 Strategy 模式来控制球的运动,并使用另一个 Strategy 模式来控制球的颜色。
然后,为许多不同类型的运动和颜色效果编写策略并使用它们的任意组合创建球将是微不足道的。但是,首先您要创建尽可能简单的策略以确保一切正常。这些策略在以后也可能很有用,因为您希望尽可能多地使用策略。

现在,最简单的策略就是没有策略。那就是什么都不做,不动也不变色。但是,策略模式要求球具有实现策略接口的对象。这就是空对象模式变得有用的地方。
只需实现一个不移动球的 NullMovementStrategy 和一个不改变球颜色的 NullColorStrategy。这两者都可以在基本上没有代码的情况下实现。这些类中的所有方法“什么都不做”。它们是空对象模式的完美示例。
Null Object 模式的关键是一个抽象类,它为该类型的所有对象定义了接口。Null Object 被实现为这个抽象类的子类。因为它符合抽象类的接口,所以可以在任何需要这种类型对象的地方使用。与使用特殊的“空”值相比,它实际上并没有实现抽象接口,并且必须在任何使用抽象接口的对象中使用特殊代码不断检查。
有时认为 Null 对象过于简单和“愚蠢”,但实际上 Null 对象总是知道需要做什么而不与任何其他对象交互。所以实际上它非常“聪明”。
结构

Client
–- 需要合作者。
AbstractObject
–- 声明客户端协作者的接口
- 酌情为所有类通用的接口实现默认行为
RealObject–- 定义 AbstractObject 的具体子类,其实例提供客户期望的有用行为
NullObject–- 提供与 AbstractObject 相同的接口,以便可以用空对象替换真实对象
- 实现它的接口什么都不做。什么都不做到底意味着什么取决于客户期望的行为类型
- 当有不止一种方法什么都不做时,可能需要多个 NullObject 类
经验法则
- Null Object 类通常实现为 Singleton。由于空对象通常没有任何状态,它的状态不能改变,所以多个实例是相同的。系统可以重复使用单个实例,而不是使用多个相同的实例。
- 如果一些客户希望空对象以一种方式什么都不做,而另一些则需要多个 NullObject 类。如果必须在运行时自定义无操作行为,则
NullObject
该类将需要可插入变量,以便客户端可以指定空对象应如何无操作(参见适配器模式中关于可插入适配器的讨论)。这通常可能是AbstractObject
没有明确定义的(语义)界面的症状。 - Null Object 不会转换为 Real Object。如果对象可能决定停止提供无操作行为并开始提供真实行为,则它不是空对象。它可能是具有无操作模式的真实对象,例如可以切换进和脱离只读模式的控制器。如果它是一个必须从无所事事对象转变为真实对象的单个对象,则应使用状态模式或代理模式来实现。在这种情况下,可以使用 Null 状态,或者代理可以持有 Null 对象。
- 空对象的使用可以类似于代理的使用,但是这两种模式有不同的用途。代理在访问真实主题时提供一定程度的间接性,从而控制对主题的访问。空协作者不会隐藏真实对象并控制对它的访问,它会替换真实对象。代理最终可能会发生变异,开始表现得像一个真实的主体。一个空对象不会变异以开始提供真实行为,它总是会提供什么都不做的行为。
- Null 对象可以是策略模式的一个特例。Strategy 指定了几个 ConcreteStrategy 类作为完成任务的不同方法。如果其中一种方法是始终不做任何事情,那
ConcreteStrategy
就是NullObject
. 例如,Controller 是 View 处理输入的 Strategy,NoController 是忽略所有输入的 Strategy。 - Null 对象可以是状态模式的一个特例。通常,每个 ConcreteState 都有一些什么都不做的方法,因为它们不适合该状态。事实上,一个给定的方法通常被实现为在大多数状态下做一些有用的事情,但在至少一个状态下什么都不做。如果一个特定的 ConcreteState 实现了它的大多数方法不做任何事情或至少给出空结果,那么它就变成了一个什么都不做的状态,因此是一个空状态。
- 空对象可用于允许访问者安全地访问层次结构并处理空情况。
- Null Object 是一个具体的合作者类,它充当需要合作者的客户的合作者。空行为并非旨在混入需要一些无操作行为的对象中。它是为一个类设计的,该类将所有可能或可能不做的行为委托给协作者。
本文来自转载,原文链接: