五. Null Object模式

背景:要从数据库中得到一个名叫Bob的员工(Employee),如果今天是其薪酬支付日期(isTimeToPay()),即为之支付薪酬(pay())。

对于长期进行C-Based语言开发的人,简单来说,代码大致如下:

Employee e = DB.getEmployee(“Bob”);

if(e != null && e.isTimeToPay()){

        e.pay();

}

这样的代码对我们长期写C-Based语言代码的人已经司空见惯,&&首在第一个表达式值为true的时候,才会执行第二个表达式。当然在也许会有人这样写:

Employee e = DB.getEmployee(“Bob”);

try{

       if(e.isTimeToPay())

     {

            e.pay();

     }

}catch(NullPointerException e){

      e.printStackTrace();

}

这两种写法本质上都没有什么错,但是都是及其繁琐的,对于经验不足的程序员,在大多时候都会忘记对e做是否为空的检查,导致异常抛出。

引入Null Object模式,即可很好的解决这个问题,即不需要对e是否为null值做检验,直接使用,不仅代码美观易懂,也排除了很多可能潜在的错误。

下面演示Null Object的魅力:

首先,建立Employee接口,如下:

import java.util.Date;

public interface Employee {

       public boolean isTimeToPay(Date payDate);

       public void pay();

      public static Employee NULL = new Employee() {

      @Override

       public void pay() {

       }

     @Override

     public boolean isTimeToPay(Date payDate) {

              return false;

     }

   };

}

该接口有一个名为NULL的静态变量持有一个匿名的Employee实体,这个匿名的实现体是无效雇员(null employee)类的唯一实例。其中isTimeToPay()返回false,而pay(0方法实现为空。

对于DB类,我们直接返回一个Employee.NULL ,以便测试:

public class DB {

      //为了测试,这里我们直接返回Employee.NULL

      public static Employee getEmployee(String name){

               //return null;

               return Employee.NULL;

      }

}

在JUnit下写出我们的测试方法:

public class TestEmployee {

     @Test

      public void testNullObject() throws Exception

      {

                Employee e = DB.getEmployee(“Bob”);

                if(e.isTimeToPay(new Date())){

                      e.pay();

         }

        assertEquals(Employee.NULL, e);

}

      @Test

       public void testCBased() throws Exception

      {

                Employee e = DB.getEmployee(“Bob”);

                if(e != null && e.isTimeToPay(new Date())){

                      e.pay();

                }

                assertEquals(null, e);

       }

      @Test

       public void testNoCheck() throws Exception

      {

                 Employee e = DB.getEmployee(“Bob”);

                 if(e.isTimeToPay(new Date())){

                         e.pay();

                 }

                 assertEquals(null, e);

        }

}

可见,使用Null Object不仅减少了代码上重复的检查对象是否为空,甚至直接排斥了那些没有良好参数检查习惯的编程人员可能会犯的错。使无效雇员类成为一个匿名类是一种确保该类只有一个实例的方法,实际上并不存在NullEmployee本身。任何其他的人都无法创建无效雇员类的其他实例。这样的话,才需要的场合我们可以使用如下表达式:

if(e == Emplyee.NULL)

如果可以创建无效雇员类的多个实例,那么以上表达式就是非常不可靠的。

长期使用C-Based语言的人习惯了返回null或者0或者-1,这样的函数返回值在使用前是必须经过检查的。NULL OBJECT模式改变了这一点。使用该模式,我们可以确保函数返回的总是有效对象,其实在他们失败时也是如此,因为这些代表失败的对象“什么也不做”。

参考:《Agile Software Development -Principles, Patterns, Practices》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值