写了个cache服务器的抽象层,如果cache中不存在该对象,我就让它返回null。
public Person fetch(String name){
//do some thing.can not find the Person.
return null;
}
头说这么不对,专家建议方法尽量不返回null,让我设置一个常量代替null,这叫 Null Object模式,于是又改成下面这样:
public Person fetch(String name){
//can not find the Person
return Person.EMPTY_PERSON;
}
据说这种模式有两个好处:
1。减少if的判断语句。
2。提高程序的健壮性,会少很多NullPointer错误。
确实,NullPointer错误应该是所有的java程序员遇到的最多的一个错误,也是比较让人头痛的错误。那次在论坛上看见一个人叫做NullPointer,我看见都很头痛。
但是这种模式真有这么神奇,可以完全消除null么?
现在我们从cache里获取了一个Person对象,要用它,那需不需要判断一下它是不是EMPTY_PERSON呢?如果需要,它和null有什么区
别?不就相当于重新定义了一个类型只能为Person的null么。如果使用者忘记检查了,直接当Person用,会有什么结果?比方调用
person.getName(),返回什么?null?这不还是会有NullPointer么,那返回空字符串?但要是更复杂的对象呢?比方要获取
Person的父亲,person.getParent(),返回什么?还是返回EMPTY_PERSON?那要是程序里要是想遍历一下person的族
谱,不就进入死循环了么。
于是我又搜索了一下相关文章,发现Null Object 模式用在下面两个场景里确实有作用:于是我又搜索了一下相关文章,发现Null Object 模式用在下面两个场景里确实有作用:
1。一种是返回集合的时候。如果返回集合时返回null,我们就必须多做一步判断:
List persons = personCache.fetchAll();
if(persons!=null){
for(Person p:persons){
p.doSometing();
}
}
但如果返回的是一个空集合,我们就不需要判断是否为null了。
2。另一个场景是在策略模式(Strategy Pattern)或者状态模式(
State Pattern)中。这两种模式下,都是要根据一定的策略或者状态进行不同的操作,这种情况下设置一个默认的do nothing的Null Object很有用。
Null Object就相当于数学上的0,它本身代表nothing,起个占位的作用,对任何操作都没有影响(当然,个别例外是可以容忍的,比方0不能做除数)。0加10000次还是0。Null Object只有在这种情况下使用才是合理的。简单的一个判断方法就是你是否能把NullObject当一般对象使用并且不影响程序的逻辑和结果。如果回答是,则使用NullObject,如果回答否,则说明这个场景不适合Null Object模式。像我开始提到的那种场景就不适合使用Null Object 模式。
最后在探讨点题外内容。如果没法用Null Object,那就只能返回null了?使用者要是忘记检查是否为null就使用,不就会有令人头痛的NullPointer错误了么?还有一个办法就是抛出强制检查的异常,逼迫使用者拦截异常进行处理。不过这种方式也有很多争议,Hibernate的接口就引起了这样的争议。想象如果从Map里获取对像的时候,如果不存在就抛出异常,那是个多痛苦的事情。曾经用过一个JSON库(好像就是官方那个),如果json里没有那个属性,它就抛出异常,导致我用的很痛苦。
另外还有一个问题就是java的方法签名设计没有体现出对返回结果的约束。比方获取map中不存在的对象会返回null,这样的信息只能从文档中得知,从签名上看不出来。同样,从签名设计也看不出来参数是否可以为null,或者是否有其他限制(比方必须是大于0的整数),只有通过看文档或者运行后得到非法参数的错误后才能知道。主要原因就是java没有内置实现 契约式设计(Design by Contract)。当然,虽然java语言中没有内置这种功能,但还是有其他实现途径,Contract4J,就是用java 5的annotation来实现契约式设计的。
相关推荐
为了解决这个问题,设计模式之一就是Null Object Pattern。这个模式的核心思想是在对象为null时提供一种默认行为,而不是抛出异常。 在C#中,我们可以创建一个“空对象”(Null Object)来模拟真实对象的行为,即使...
在许多面向对象的程序设计...NullObject模式能够用来解决这一问题。本文阐述了NullObject模式及其实现方式,针对空目标的单一实例化策略,给出了改进措施。NullObject模式对去除重复检测和减少空引用异常有较明显的效果。
设计模式之 Template(模板方法) 实际上向你介绍了为什么要使用 Java 抽象类,该模式原理简单,使用很普遍. 设计模式之 Strategy(策略) 不同算法各自封装,用户端可随意挑选需要的算法. 设计模式之 Chain of ...
2. **默认值或空对象模式**:提供一个默认值或“占位符”对象,以便在实际值为null时使用。在Kotlin中,可以使用Elvis操作符 `object?.method() ?: defaultMethod()`,如果object为null,则执行defaultMethod。 3. ...
空对象模式(Null Object Pattern) 策略模式(Strategy Pattern) 模板模式(Template Pattern) 访问者模式(Visitor Pattern) 4. J2EE 模式 MVC 模式(MVC Pattern) 业务代表模式(Business Delegate ...
23种java版设计模式源码案例.zip 0.目录 创建型模式(creational) 简单工厂(simplefactory) 动态工厂(dynamic) ...空对象模式(null object) 策略模式(strategy) 模板模式(template) 访问者模式(visitor)
BuildPipeline.BuildAssetBundle(Selection.objects, null, savaPath, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows); } } ``` 这段代码首先获取当前选中的CSV文件对象,然后将每个CSV文件的...
第17章 NULL OBJECT模式 第18章 薪水支付案例研究:第一次迭代开始 第19章 薪水支付案例研究:实现 第四部分 打包薪水支付系统 第20章 包的设计原则 第21章 FACTORY模式 第22章 薪水支付案例研究(第2部分) 第五...
空对象模式(Null Object Pattern) 策略模式(Strategy Pattern) 模板模式(Template Pattern) 访问者模式(Visitor Pattern) 4 J2EE 模式 这些设计模式特别关注表示层。这些模式是由 Sun Java Center 鉴定的。 ...
我想每个人都有一种经历,为了获取某属性,但是有时候属性是None,那么需要你做异常处理, 而假如你想节省这样的条件过滤的代码,可以使用Null模式以减少对象是否为None的判断 python的例子 我举个不是很通用的例子...
空对象模式(Null Object Pattern)是一种行为设计模式,它允许我们在不返回 null 的情况下提供默认行为。这种模式通常用于需要处理 null 对象的情况下,以避免NullPointerException 异常。 在软件设计中,我们经常...
第21章 COMMAND模式和ACTIVE OBJECT模式:多功能与多任务 第22章 TEMPLATE METHOD模式和STRATEGY模式:继承和委托 第23章 FACADE模式和MEDIATOR模式 第24章 SINGLETON模式和MONOSTATE模式 第25章 NULL OBJECT模式 ...
private static object syncRoot = new object(); private Singleton() { } public static Singleton Instance { get { if (instance == null) { lock (syncRoot) { if (instance == null) { ...
public void update(Observable o, Object arg) { // 更新显示的数据 } } ``` 以上是关于工厂模式、单例模式和观察者模式的基本介绍和Java实现。这些设计模式在实际编程中有着广泛的应用,能帮助我们编写出更...
总结,JavaScript的构造函数模式是创建对象的主要方式之一,它结合原型和原型链提供了面向对象编程的基础。理解并掌握这一模式有助于编写可维护、可扩展的代码。在实际开发中,构造函数模式常常与其他设计模式(如...
第十七章 NULL OBJECT模式 第十八章 薪水支付案例研究:第一次迭代开始 第十九章 薪水支付案例研究:实现 第Ⅳ部分 打包薪水支付系统 第二十章 包的设计原则 第二十一章 FACTORY模式 第二十二章 薪水支付案例研究...
private static object syncRoot = new object(); private Singleton() {} public static Singleton Instance { get { if (instance == null) { lock (syncRoot) { if (instance == null) { instance...