在面向对象的编程中,行为会被封装成类的方法,暴露方法的行为结果一般有三种方式:
1.返回一个处理结果对象(Object),非void
2.抛出不同种类的异常,调用者通过判断异常来区分处理结果
3.修改入参的对象,即通过方法的副作用来暴露方法的处理结果,此种方法一般用于返回多个对象
首先我们最常用的是第一种方式,即方法处理完成之后,返回一个结果,该结果的如何使用以及该结果的作用域完全由使用者来决定. 由于返回的是明确的结果,故而方法在执行过程中,不会影响调用者的执行过程,相对于throw exception来说.
自然,throw exception则一般是用户尽快结束程序.往往是用于发生了不可修复的异常.在一个业务流程中,某一环节发生异常,程序继续执行已没有任何意义时.当然,还有部分异常时强制性的,比如读取文件等异常.从设计目的来说,如果是为了控制业务流程,不建议使用exception,建议使用明确的返回结果,调用者可以根据返回结果来决定是否继续执行,以及如何执行.
那么通过方法的副作用来完成业务逻辑,是否可取?不可否认的,存在即有它的作用.通过副作用来实现业务逻辑,与面向对象的封装是背道而驰的.一个行为,不修改传入的数据,返回一个新的结果,不对调用者的任何数据进行修改,实现数据上的隔离,保证各个行为(method)之间是相互独立的.行为之间的相互独立,无论是迁移还是重构,都会变得轻松.另外,使用副作用来完成业务逻辑时,还要考虑引用传值,以及资源竞争(比如来修改文件或者数据库中的数据)的问题.
下面附上代码片段来说说exception控制业务流程的一些问题:
package com.test.demo;
/**
* yingyinglicai.com Inc.
* Copyright (c) 2013-2016 All Rights Reserved.
*
* @author ZhangZhong
* @version v 0.1 2016/11/27 10:44 Exp $$
*/
public class CAbc {
public boolean method_a_return(){
System.out.println("method_a_return");
return true;
}
public void method_a_exception() throws Exception {
throw new Exception("method_a_exception");
}
public void method_a_runtime_exception(){
throw new RuntimeException("method_a_runtime_exception");
}
public boolean method_b_return(){
System.out.println("method_b_return");
return true;
}
public void method_b_exception() throws Exception {
throw new Exception("method_b_exception");
}
public void method_b_runtime_exception(){
throw new RuntimeException("method_b_runtime_exception");
}
}
package com.test.demo;
/**
* yingyinglicai.com Inc.
* Copyright (c) 2013-2016 All Rights Reserved.
*
* @author ZhangZhong
* @version v 0.1 2016/11/27 10:44 Exp $$
*/
public class CXyz {
public boolean method_x_return(){
System.out.println("method_x_return");
return true;
}
public void method_x_exception() throws Exception {
throw new Exception("method_x_exception");
}
public void method_x_runtime_exception(){
throw new RuntimeException("method_x_runtime_exception");
}
public boolean method_y_return(){
System.out.println("method_y_return");
return true;
}
public void method_y_exception() throws Exception {
throw new Exception("method_y_exception");
}
public void method_y_runtime_exception(){
throw new RuntimeException("method_y_runtime_exception");
}
}
package com.test.demo;
/**
* yingyinglicai.com Inc.
* Copyright (c) 2013-2016 All Rights Reserved.
*
* @author ZhangZhong
* @version v 0.1 2016/11/27 10:49 Exp $$
*/
public class CBiz {
private CXyz cXyz;
private CAbc cAbc;
/**
* 当发生异常,立即终止方法
* @return
*/
public boolean flow_return_when_exception() {
try {
cAbc.method_a_return();
cXyz.method_x_return();
cXyz.method_x_exception();
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 当发生异常,继续执行其他部分异常
* @return
*/
public boolean flow_no_return_when_exception() {
try {
cAbc.method_a_return();
cXyz.method_x_exception();
} catch (Exception e) {
e.printStackTrace();
System.out.println("no return even exception but continu");
}
cXyz.method_x_return();
return true;
}
/**
* 发生异常,继续执行,若再发生异常,仍旧继续执行
* @return
*/
public boolean flow_no_return_when_exception_further() {
try {
cAbc.method_a_return();
cXyz.method_x_exception();
} catch (Exception e) {
e.printStackTrace();
System.out.println("no return even exception but continu");
}
cXyz.method_x_return();
try {
assert cAbc.method_b_return();
cXyz.method_y_exception();
} catch (Exception e) {
e.printStackTrace();
System.out.println("no return even exception but continu");
}
cXyz.method_y_return();
return true;
}
/**
* 明确在某些步骤执行失败时,终止
* @return
*/
public boolean clear_return_when_false() {
try {
assert cAbc.method_a_return();
cAbc.method_b_return();
cXyz.method_x_return();
assert cXyz.method_y_return();
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
}
本文作者:猫小鞭