内容简介:在大多数面向对象的语言中,例如Java或C#,引用可能为null。在调用任何方法之前,需要检查这些引用以确保它们不为null,因为通常无法在空引用上调用方法。不使用空引用来表示对象的缺失(例如,不存在的客户),而是使用实现预期接口但其方法体为空的对象。这种方法优于工作默认实现的优点是Null对象是非常可预测的并且没有副作用:它什么都不做。
目的
在大多数面向对象的语言中,例如 Java 或C#,引用可能为null。在调用任何方法之前,需要检查这些引用以确保它们不为null,因为通常无法在空引用上调用方法。不使用空引用来表示对象的缺失(例如,不存在的客户),而是使用实现预期接口但其方法体为空的对象。这种方法优于工作默认实现的优点是Null对象是非常可预测的并且没有副作用:它什么都不做。
结构
参与者:
Client
- 需要合作者。
AbstractObject
- 声明Client的协作者的接口。
- 根据需要,为所有类共有的接口实现默认行为。
RealObject
- 定义AbstractObject的具体子类,其实例提供Client期望的有用行为。
NullObject
- 提供与AbstractObject相同的接口,以便可以用空对象替换真实对象。
- 实现其接口以不执行任何操作。什么都不做的确切含义取决于Client期望的行为类型。
- 当有多个方法可以不做任何事情时,可能需要多个NullObject类。
合作
客户端使用AbstractObject类接口与其协作者进行交互。如果接收者是RealObject,则处理该请求以提供真实行为。如果接收者是NullObject,则通过不执行任何操作或至少提供空结果来处理请求。
源代码
空对象模式 用中性对象替换空值。很多时候,这简化了算法,因为不需要额外的空值检查。
在此示例中,我们构建了一个二叉树,其中节点是正常对象或空对象。树中没有使用空值,使遍历变得容易。
步骤1: 通过参考类图,让我们创建接口 - 节点 接口
<font><i>/** * * Interface for binary tree node. * */</i></font><font> <b>public</b> <b>interface</b> Node { String getName(); <b>int</b> getTreeSize(); Node getLeft(); Node getRight(); <b>void</b> walk(); } </font>
步骤2: 为二叉树的普通节点创建实现。
<b>public</b> <b>class</b> NodeImpl implements Node { <b>private</b> <b>static</b> <b>final</b> Logger LOGGER = LoggerFactory.getLogger(NodeImpl.<b>class</b>); <b>private</b> <b>final</b> String name; <b>private</b> <b>final</b> Node left; <b>private</b> <b>final</b> Node right; <font><i>/** * Constructor */</i></font><font> <b>public</b> NodeImpl(String name, Node left, Node right) { <b>this</b>.name = name; <b>this</b>.left = left; <b>this</b>.right = right; } @Override <b>public</b> <b>int</b> getTreeSize() { <b>return</b> 1 + left.getTreeSize() + right.getTreeSize(); } @Override <b>public</b> Node getLeft() { <b>return</b> left; } @Override <b>public</b> Node getRight() { <b>return</b> right; } @Override <b>public</b> String getName() { <b>return</b> name; } @Override <b>public</b> <b>void</b> walk() { LOGGER.info(name); <b>if</b> (left.getTreeSize() > 0) { left.walk(); } <b>if</b> (right.getTreeSize() > 0) { right.walk(); } } } </font>
步骤3: 二叉树节点的空对象实现。
实现为Singleton,因为所有NullNodes都是相同的。
<b>public</b> <b>final</b> <b>class</b> NullNode implements Node { <b>private</b> <b>static</b> NullNode instance = <b>new</b> NullNode(); <b>private</b> NullNode() {} <b>public</b> <b>static</b> NullNode getInstance() { <b>return</b> instance; } @Override <b>public</b> <b>int</b> getTreeSize() { <b>return</b> 0; } @Override <b>public</b> Node getLeft() { <b>return</b> <b>null</b>; } @Override <b>public</b> Node getRight() { <b>return</b> <b>null</b>; } @Override <b>public</b> String getName() { <b>return</b> <b>null</b>; } @Override <b>public</b> <b>void</b> walk() { <font><i>// Do nothing</i></font><font> } } </font>
步骤4: 让我们使用客户端测试这个Null对象设计模式。
<b>public</b> <b>class</b> Client{ <font><i>/** * Program entry point * * @param args command line args */</i></font><font> <b>public</b> <b>static</b> <b>void</b> main(String[] args) { Node root = <b>new</b> NodeImpl(</font><font>"1"</font><font>, <b>new</b> NodeImpl(</font><font>"11"</font><font>, <b>new</b> NodeImpl(</font><font>"111"</font><font>, NullNode.getInstance(), NullNode.getInstance()), NullNode.getInstance()), <b>new</b> NodeImpl(</font><font>"12"</font><font>, NullNode.getInstance(), <b>new</b> NodeImpl(</font><font>"122"</font><font>, NullNode.getInstance(), NullNode.getInstance()))); root.walk(); } } </font>
输出:
适用性
使用Null对象模式时希望避免显式空检查并保持算法优雅且易于阅读。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 设计模式 - 数据访问对象模式
- JavaScript设计模式之面向对象编程
- 重温设计模式系列(二):面向对象基础知识
- 常用设计模式/容器/依赖注入/静态代理/请求对象
- <<深入PHP面向对象、模式与实践>>读书笔记:面向对象设计和过程式编程
- 使用组合的设计模式 —— 找对象要用的远程代理模式
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
大数据架构商业之路
黄申 / 机械工业出版社 / 2016-5-1 / 69.00元
目前大数据技术已经日趋成熟,但是业界发现与大数据相关的产品设计和研发仍然非常困难,技术、产品和商业的结合度还远远不够。这主要是因为大数据涉及范围广、技术含量高、更新换代快,门槛也比其他大多数IT行业更高。人们要么使用昂贵的商业解决方案,要么花费巨大的精力摸索。本书通过一个虚拟的互联网O2O创业故事,来逐步展开介绍创业各个阶段可能遇到的大数据课题、业务需求,以及相对应的技术方案,甚至是实践解析;让读......一起来看看 《大数据架构商业之路》 这本书的介绍吧!