今天写程序,用了一个简单工厂模式,工厂类有一个静态工厂方法,传入一个参数,根据参数生成不同的对象: 
代码
public static GateWayCaller getGateWayCaller(String serviceKey)   
{   
    if("alerting".equals(serviceKey))   
    {   
        return new AlertingCaller();   
    }   
    else if("report".equals(serviceKey))   
    {   
        return new ReportCaller();   
    }   
    //...   
    else  
    {   
        return null;   
    }   
}   
一同事硬说我return null不对,应该抛出一个checked异常,由客户端调用者去处理该异常。我的想法很简单,既然这是一个生成对象的方法,如果调用者将参数传错导致要生成的对象不存在,就应该返回一个空对象,而不是抛出异常。不然的话所有客户端代码都要处理一个没用的异常!!搞的好郁闷,最受不了的是老说我什么什么观点是错误的。俺也没有什么太多的编程经验,也不知道该怎么去反驳。我认为没有哪个观点是绝对错误的,只有比较之下哪种做法更好一点?听听大家的意见?

解决方案 »

  1.   

    你的同事说的只能说是一种解决方案,但并不是说你现在这个就不对。至于抛不抛异常,完全应该有应用的需要来决定。如果按你的写法,你的javadoc里应该注明,在什么情况下,此方法返回null值,这是个好习惯。题外话:如果是sting值映射到一个实例的情况,建议用个map来做,不要用if,一是代码难看,二是维护成本增加。如果你的那几个Caller都是单例的,那map里直接放个实例就行;如果不能是单例的,那就放个Class对象,然后用调用其newInstance()方法;如果需要特殊的构造,可以写个接口来专门做构造。
      

  2.   

    你同事的观点是对的,应该抛出异常。你返回null的话,看似简单,其实会让别人很头痛。这是因为:1. 他一直要到用到这个返回对象的时候才知道他得到的是一个null(通过运行时的NullPointerException得知)。
    2. 他只知道他得到了一个null,却不知道实际原因是什么,实际上的原因是他传入了不被接受的参数,但返回null并没有告诉他这一点。所以,建议你的代码写成这样:
        if("alerting".equals(serviceKey))   
            return new AlertingCaller();  
        else if("report".equals(serviceKey))
            return new ReportCaller();
        //...   
        else  
            throw new RuntimeException("Invalid Service Key!");这样如果传入的参数不是方法所接受的,运行时就会打印出合适的消息,这比得到一个NullPointerException要好得多。
      

  3.   

    楼上manbaum说的很对。写javadoc是个好习惯。但个人认为javadoc没有强制性,不是所有人都会去看。
      

  4.   

    但他的观点是要抛出checked exception,这样的话客户端就很烦了~所有调用的地方都要去做无用的异常处理~
      

  5.   

    是抛出RuntimeException还是checked exception不是该问题的关键,但抛出exception,这个大方向是对的。
    相信你和你的同事不是在抛出RuntimeException还是checked exception这一点上存在分歧。
    题外话:作为新手要虚心,别人的意见即使是错的也不要急于反驳,先自己好好想一想。
      

  6.   

    3楼的说法有道理,但也不见得必须抛异常,我觉得,还是要看应用决定。返回null已经说明了,你传入的参数不可被接受,只不过我处理的很温和,返回一个null,让调用者自己去做if检查,然后体面的做后续处理。抛异常的话,需要catch/finally才能解决异常时资源释放问题,即使如此,有时候还会解决不好。抛runtime异常也是个好办法,我的观点是,runtime异常表示的是系统不期望的异常,也就是说正常逻辑下不应该出现的异常,如果出现了,说明编码中出现了错误。所以这里的runtime异常是说,在系统测试期间,如果测出报这个异常,那说明调用者的代码写错了。在有些情况下,也可以抛checked异常。那就是说,我明确的指出,这个方法不接受不可识别的参数值。抛checked异常的意义就在于让调用者必须catch,这样防止偷懒的程序员不做处理或者记性不好的程序员忘记处理,仅此而已。但这些也可以通过其他手段来避免,比如代码复查,覆盖式测试等等。
      

  7.   

    没错,依具体情况而定。如果你的团队是个默契度很高的团队,管用的方法就会很多。但通常而言,返回null这种做法会导致更多潜在的问题,而抛出异常意味着“我产生的问题我负责”,这能使单个方法的独立性和可靠性更高。个人赞成抛出异常。