[翻译]空对象设计模式(Null Object Design Pattern)

        这是我翻译的第一篇网站文章,虽然文章内容比较简单,但是我还是觉得不容易翻译,很多句子都是可以意会,但是不知道怎么写出来。下面是译文:

空对象设计模式

意图

空对象设计模式通过提供可替代的方案来解决对象引用不存在时引起的问题,该方案提供适当的不引发任何动作的对象默认值。简而言之,空对象设计模式不会对程序产生任何影响。

在以下情况下使用空对象模式:

  • 对象实例需要一个协作实例。空对象模式不会引入协作实例——它只是使用现有的协作实例;
  • 一些协作实例什么都不需要做;
  • 从客户端中将对象实例不存在的处理抽象出来。

问题

假如对象引用可以为空,如果检测到对象引用为空,要么什么都不做,要么为程序设置一些默认值。怎样才能在程序中透明地处理对象引用为空的情况?

讨论

有时候一个类需要协作类并不是期望它做任何事,但是这个类期望程序像调用有实际动作的实体类一样调用协作类。

以屏幕保护程序为例,屏幕保护程序运行时显示多个球,并且这些球有不同的颜色特效。该屏幕保护程序很容易实现,通过创建一个球的类来代表屏幕保护程序中的球,并且使用策略模式(Strategy Pattern)来控制每个球的移动和颜色特效。

接着就是些繁琐的工作,编写球的不同的移动策略、编写球的不同的颜色特效策略,然后创建包含不同移动策略和颜色特效策略组合的球实例。但是,程序启动时,你希望能够创建最简单的策略以确保程序能够正常运行,并且这些策略在程序运行时也照样能用。

最简单的策略就是没有策略,也就是什么都不做,使用最简单的策略,球既不会移动,球的颜色也不会变化。不过策略模式要求球使用的策略都必须实现预先定义好的接口。这就是空对象模式的用武之地。

以“移动策略基类”为基类实现“空移动策略”类,包含该类对象的球不做任何移动;以“颜色特效策略基类”为基类实现“空颜色特效策略”类,包含该类对象的球不会更改球的颜色。本质上实现这两类子类不需要多少代码,这两类子类中的函数什么都不做。这是空对象模式的最好范例。

应用空对象模式的关键是定义一个适用于该类型所有对象实例的抽象类,然后定义一个继承此抽象类的空对象类。由于该空对象类实现了抽象类定义的所有接口,它可以被用于任何其它子类(同样继承于此抽象类)运行的场合。相比之下,选择不创建实现该抽象类的空对象子类,就必须在所有使用此抽象类的地方检查对象引用是否为空。

有时会觉得空对象模式太简单了,甚至有点“傻”,事实上一个空对象模式创建的对象不需要和其他对象做交互就可以了解合适的响应,所以其实它很“聪明”。

结构

 

n 客户类

u 它需要一个协作对象以完成某类操作

n 抽象类

u 为协作对象声明接口

u 为所有子类提供默认的行为

n 实际对象类

u 继承自抽象类,提供客户类期望的操作

n 空对象类

u 继承自抽象类,可以替代实际对象类使用

u 不做任何操作,但是“不做任何操作”的具体含义由客户端期望的操作决定

u 当有多种方式可以实现“不做任何操作”,可能需要对每种实现方式创建一类空对象类

经验

n 空对象类经常采用单件模式(Singleton)实现。由于空对象类通常不包含任何状态属性,它的实例对象的状态不会改变,也就是多个实例对象的内容都是相同的。与其使用多个相同的对象实例,程序可以采用单件模式重复使用同一空对象实例。

n 如果不同的客户类要求空对象实例“不作任何操作”的的方式不同,那么需要定义多个空对象类。如果“不做任何操作”的行为必须在程序运行时指定,则空对象类中需要定义变量使客户类可以指定具体的“不做任何操作”的方式。通常这表明抽象类的接口没有定义好。

n 空对象类不会转换为实际对象类。如果空对象类不再“不做任何操作”,而是提供客户类需要的实际操作,那它就不是空对象类,而是一个披着空对象类外衣的实际对象类,例如一个可以切换只读模式的控制类。如果一个对象可以从空对象转变为实际对象,那它应该采用状态模式实现(State),也可以用代理模式(Proxy),这样的话,可能会使用一个空状态或者代理类来包含空对象。

n 空对象模式与代理模式的使用方式类似,但是这两个模式的目的不同。代理模式提供间接层来访问一个实际主体,它控制对主体的访问。空对象类并不隐藏实际对象类,也不控制对实际对象类的访问,而是替代实际对象类。代理类最终会变的像一个真正的主体,但空对象类不会转而提供实际的操作,它始终“不做任何操作”。

n 空对象模式是策略模式的一个特例。策略模式实现多类具体策略类来完成一个任务,如果其中一个具体策略类始终“不做任何操作”,那这个具体策略类就是一个空对象类。例如,Controller类作为观察策略类处理外部输入,而NoController类则是忽略任何外部输入的策略类,NoController类就是空对象类。

n 空对象模式是状态模式的一个特例。通常每个具体状态类都有一些“不做任何操作”的方法,因为这些方法不适合当前状态。实际上,一个特定的方法适用于多数状态,但是对一个或者多个状态,这个方法“不做任何操作”。如果一个特定的具体状态类中多数方法“不做任何操作”或者返回空的结果,该类就变成了一个“不做任何操作”的状态,也就是一个空状态。

n 空对象模式可以允许访问者安全地访问数据层,并且可以处理数据为空的情形。

n 对于需要协作类的客户类而言,空对象类是实实在在的协作类。“不作任何操作”的行为并不混同于没有行为。“不作任何操作”的行为对于一个协作类来讲,可能没有行为,也可能是有行为(比如提供默认值)。

 

原文地址:http://sourcemaking.com/design_patterns/null_object

另外我还写了一个很简单的示例程序,可以的到

https://onedrive.live.com/?cid=423921156EB9AD66&id=423921156EB9AD66%21105里面去下载,文件名为NullObjectPatternExample.rar。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值