咱们常见的一个例子java
Employee employee = DB.getEmployee("bob"); if(employee!=null && employee.isTimeToPay(today)){ employee.pay(); }
这个是从DB中取得名称为bob的雇员,若是取获得了,而且今天是发薪日,则会支付。咱们会常常写这种判断对象为空的代码,这种写法不只丑陋并且很是容易出错,若是咱们有些地方没有判断而调用了空对象的属性或者方法,将会抛出NullpointException,那若是咱们不使用这种判断而在DB的getEmployee方法中抛出异常的方式,这样讲会变得更加麻烦,咱们须要把相关代码用try catch包括起来,而后还得进行处理。ide
这种状况咱们可使用NULL OBJECT模式来解决这些问题,一般改模式会消除对null值进行检查的须要,而且有助于代码的简化。测试
大体的思路是咱们有两个实现了Employee接口的对象,一个是正常的EmployeeImp,另一个是空的对象NullEmployee,当DB中取不到名字为bob的对象时,会返回NullEmployee对象。NullEmployee实现了Employee中的全部方法,可是方法中“什么也没作”,“什么也没作”的含义和具体的方法语境有关。例如,有人会指望isTimeToPay方法被实现为返回false,由于根本不会为NullEmployee支付薪水。
使用这个模式,最初的代码会更改成这样:spa
Employee employee = DB.getEmployee("bob"); if(employee.isTimeToPay(today)) employee.pay();
这种代码既不容易出错,也不丑陋。而且具备很好的一致性。DB.getEmployee中总会返回一个Employee的实例,无论是否找获得雇员,均可以保证返回的实例具备合适的行为。
固然,在不少状况下,仍然想要知道是否DBEmployee没有招到雇员。在Employee中建立持有惟一NullEmployee实例的static final变量就能够达到这个目的。
测试程序:
code
Public void testNull() throws Exception{ Employee e = DB.getEmployee(“bob”); if(e.isTimeToPay(new Date())){ fail(); } assertEquals(Employee.NULL,e); }
下面程序展现了DB类。为了方便测试,getEmployee方法只返回EmployeeNULL。对象
Public class DB{ Public static Employee getEmployee(String name) { Return Employee.NULL; } }
接下来程序就是展现Employee接口。该接口中有一个名为NULL的静态变量,持有一个匿名的实现体是无效雇员(NULL Employee)类惟一的实例,其中isTimeToPay返回false,pay方法则为空。
接口
import java.util.Date; /** * Created by wangtf on 2015/12/22. */ public interface Employee { public boolean isTimeToPay(Date date); public void pay(); public static Employee NULL = new Employee() { @Override public boolean isTimeToPay(Date date) { return false; } @Override public void pay() { } }; }
使无效雇员类成为一个匿名内部类是一种确保该类只有一个单一实例的方法。实际上并不存在NullEmployee类自己。其余任何人都没法建立无效雇员的其余实例。这是很是好的,由于咱们指望的表达方式是:
if(e==Employee.NULL)
若是能够建立无效雇员的多个实例,那么这种表达方式就是部可靠的get