设计模式
设计模式简介
看懂UML类图和时序图
UML统一建模语言
UML类图及类图之间的关系
类关系记忆技巧
如何正确使用设计模式
优秀设计的特征
面向对象设计原则
创建型设计模式
工厂模式
抽象工厂模式
简单工厂模式
静态工厂模式(Static Factory)
单例模式
建造者模式
原型模式
结构型设计模式
适配器模式
桥接模式
组合模式
装饰器模式
外观模式
享元模式
代理模式
过滤器模式
注册模式(Registry)
行为型设计模式
责任链模式
命令模式
解释器模式
中介者模式
备忘录模式
迭代器模式
观察者模式
状态模式
策略模式
模板模式
访问者模式
规格模式(Specification)
J2EE 设计模式
MVC 模式
业务代表模式
组合实体模式
数据访问对象模式(DAO模式)
前端控制器模式
拦截过滤器模式
空对象模式
服务定位器模式
传输对象模式
数据映射模式(Data Mapper)
依赖注入模式(Dependency Injection)
流接口模式(Fluent Interface)
其他模式
对象池模式(Pool)
委托模式
资源库模式(Repository)
实体属性值模式(EAV 模式)
反面模式
归纳设计模式
本文档使用 MrDoc 发布
-
+
首页
空对象模式
> 空对象不做任何动作,在数据不可用的时候提供默认的行为。 ![Null](/media/202203/2022-03-15_1423520.9643639938458195.png) 空对象模式 (null object Pattern)是一种软件设计模式。可以用于返回无意义的对象时,它可以承担处理 null 的责任。有时候空对象也被视为一种设计模式。 在空对象模式(Null Object Pattern)中,一个空对象取代 NULL 对象实例的检查。Null 对象不是检查空值,而是反应一个不做任何动作的关系。这样的 Null 对象也可以在数据不可用的时候提供默认的行为。 在空对象模式中,我们创建一个指定各种要执行的操作的抽象类和扩展该类的实体类,还创建一个未对该类做任何实现的空对象类,该空对象类将无缝地使用在需要检查空值的地方。 ## 问题 在一个图书信息查询系统中,你调用一个方法,传过去你要查找图书的 ID,然后它返回给你,你要查找的图书对象,这样你就可以调用对象的方法来输出图书的信息。 空指针报错是最为常见的一种错误。比较常规的做法就是加一个判断,判断是否为 null。如果为 null 的话,就不再调用后面的行为。 这样做,确实消除了报错,但是这样做真的好吗?你想如果在一段程序中有很多处调用 getBook()方法或者有很多个客户端的话,岂不是很多处都要判断 book 对象是否为 null?这还不算坏,如果哪一处没有判断,然后报错了,很有可能导致程序没法继续运行甚至崩溃。而且,永远都不要太相信客户端,不要把整个程序的稳定性寄托在客户端身上。像上面的处理方法,当获取对象为 null 的时候,输出的提示信息是有客户端来定制的,这样岂不是把主动权交给了客户端,而不是我们系统本身? ## 目的 空对象模式不属于 GoF 设计模式,但是它作为一种经常出现的套路足以被视为设计模式了。它具有如下优点: - 客户端代码简单 - 可以减少报空指针异常的几率 - 测试用例不需要考虑太多条件 ## 结构 ![空对象模式](/media/202203/2022-03-15_1430010.44077947013158025.png) 空对象模式主要包含 3 个角色。 - 抽象对象(AbstractObject):定义所有子类公有的行为和属性。 - 真实对象(RealObject):继承 AbstractObject 类,并实现所有行为。 - 空对象(NullObject):继承 AbstractObject 类,对父类方法和属性不做实现和赋值。 ### 实例 我们将创建一个定义操作(在这里,是客户的名称)的 *AbstractCustomer* 抽象类,和扩展了 *AbstractCustomer* 类的实体类。工厂类 *CustomerFactory* 基于客户传递的名字来返回 *RealCustomer* 或 *NullCustomer* 对象。 *NullPatternDemo* ,我们的演示类使用 *CustomerFactory* 来演示空对象模式的用法。 ![空对象模式的 UML 图](/media/202203/2022-03-15_1430510.3278398348048305.png) ## 应用场景 空对象模式适用于以下应用场景。 - 对象实例需要一个协作实例。空对象模式不会引入协作实例,它只是使用现有的协作实例。 - 部分协作实例不需要做任何处理。 - 从客户端中将对象实例不存在的代码逻辑抽象出来。 ## 优点 - 它可以加强系统的稳固性,能有效地减少空指针报错对整个系统的影响,使系统更加稳定。 - 它能够实现对空对象情况的定制化的控制,掌握处理空对象的主动权。 - 它并不依靠 Client 来保证整个系统的稳定运行。 - 它通过定义 isNull()对使用条件语句==null 的替换,显得更加优雅,更加易懂。 ## 缺点 - 每一个要返回的真实的实体都要建立一个对应的空对象模型,那样会增加类的数量。 ## 代码示例 ``` public abstract class AbstractCustomer { protected String name; public abstract boolean isNil(); public abstract String getName(); } public class RealCustomer extends AbstractCustomer { public RealCustomer(String name) { this.name = name; } @Override public String getName() { return name; } @Override public boolean isNil() { return false; } } public class NullCustomer extends AbstractCustomer { @Override public String getName() { return "Not Available in Customer Database"; } @Override public boolean isNil() { return true; } } public class CustomerFactory { public static final String[] names = {"Rob", "Joe", "Julie"}; public static AbstractCustomer getCustomer(String name){ for (int i = 0; i < names.length; i++) { if (names[i].equalsIgnoreCase(name)){ return new RealCustomer(name); } } return new NullCustomer(); } } public class NullPatternDemo { public static void main(String[] args) { AbstractCustomer customer1 = CustomerFactory.getCustomer("Rob"); AbstractCustomer customer2 = CustomerFactory.getCustomer("Bob"); AbstractCustomer customer3 = CustomerFactory.getCustomer("Julie"); AbstractCustomer customer4 = CustomerFactory.getCustomer("Laura"); System.out.println("Customers"); System.out.println(customer1.getName()); System.out.println(customer2.getName()); System.out.println(customer3.getName()); System.out.println(customer4.getName()); } } ```
追风者
2022年3月29日 20:06
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
关于 MrDoc
觅思文档MrDoc
是
州的先生
开发并开源的在线文档系统,其适合作为个人和小型团队的云笔记、文档和知识库管理工具。
如果觅思文档给你或你的团队带来了帮助,欢迎对作者进行一些打赏捐助,这将有力支持作者持续投入精力更新和维护觅思文档,感谢你的捐助!
>>>捐助鸣谢列表
微信
支付宝
QQ
PayPal
Markdown文件
分享
链接
类型
密码
更新密码