一种称为 Null Object Pattern 的行为设计模式提供了一个对象来表示接口的缺失对象。如果 null 对象会导致 null 引用异常,则这是提供替代行为的一种方法。在本文中,我们将深入探讨 C# Null Object 模式,逐步介绍更复杂的情况。
一种使使用可能未定义的依赖项更容易的设计方法是 Null 对象模式。这是通过使用实现已识别接口的具体类的实例来实现的,而不是使用 null 引用。创建一个抽象类,其中概述了要执行的不同操作,以及扩展它的具体类和一个空对象类,该类提供了该类的无所事事版本,可以在我们需要检查空值的任何地方使用。
依赖于扩展抽象 DependencyBase 类或实现 Dependency 接口的对象的代码称为客户端。客户端使用此对象来执行任务。Client 端应该能够以相同的方式处理 real 和 null 对象,而不必知道它正在处理哪种类型的对象。
名为 DependencyBase 的抽象类或接口指定必须由所有具体依赖项(包括 null 对象)实现的方法。所有依赖项都必须遵守的协定由此类定义。
Client 可以将此类用作函数依赖项。客户端无需知道 Dependency 对象是 actual 还是 null 即可与它们交互。
这是客户端可以用作依赖项的 null 对象的类。虽然它实现了 DependencyBase 抽象类指定的每个成员,但它缺乏功能。系统中的 null 或不存在的依赖项由 NullObject 表示。客户端可以安全地调用 NullObject 上的方法,而不会导致错误或需要 null 检查。
举个例子,
下面是 ICar.cs 文件的代码。
public interface ICar
{
void Drive();
void Stop();
}
下面是 SedanCar.cs 文件的代码。
public class SedanCar : ICar
{
public void Drive()
{
Console.WriteLine("Drive the sedan car.");
}
public void Stop()
{
Console.WriteLine("Stop the sedan car.");
}
}
下面是 NullCar.cs 文件的代码。
public class NullCar : ICar
{
public void Drive()
{
}
public void Stop()
{
}
}
下面是 CarService.cs 文件的代码。
public class CarService(ICar car)
{
private readonly ICar _car = car;
public void Run()
{
Console.WriteLine($"Start run method. {nameof(ICar)}: {_car}");
_car.Drive();
_car.Stop();
Console.WriteLine($"Complete run method. {nameof(ICar)}: {_car}");
Console.WriteLine();
}
}
下面是 Program.cs 文件的代码。
var sedanCar = new SedanCar();
var carService = new CarService(sedanCar);
carService.Run();
var nullCar = new NullCar();
carService = new CarService(nullCar);
carService.Run();
如果要提供对象功能的默认或无操作实现以避免 null 检查并正常处理 null 引用,可以使用 Null 对象设计模式。以下情况需要应用 Null 对象设计模式。
Null 对象设计模式可能不适用于以下情况。
Null Object Pattern(一种设计模式)提供了一种处理缺少对象的可靠方法。它通过提供默认行为并消除 null 检查的必要性,降低了运行时错误的可能性并简化了客户端代码。为了提高稳定性和可维护性,在构建新系统或重构旧系统时,Null Object Pattern 可能是一个有用的工具。