Convert Dynamic to Static Construction -- 动态到静态构造转换
Refactoring contributed by Gerard M. Davison
You have code that loads other classes dynamically. This can introduce a un-warranted overhead and can produce code that is more fragile.
你有一段代码利用反射加载一个类。这种方式开销大并且代码较脆弱。
Replace the dynamic class loading with static code.
以静态代码取代动态类加载代码。
try { DataProvider dp = (DataProvider) Class.forName("org.davison.data.jdbc.JDBCProvider").newInstance();//利用反射加载类。1、开销大 2、较脆弱 3、异常处理太多 4、编译期,有些错误无法检查。 } catch (IllegalAccessException iae) { // Convert exception to error to preseve the interface. // throw new IllegalAccessError(iae.getMessage()); } catch (InstantiationException ie) { // Convert exception to error to preseve the interface. // throw new InstantiationError(ie.getMessage()); } catch (ClassNotFoundException cnfe) { // Convert exception to error to preseve the interface. // throw new NoClassDefFoundError(cnfe.getMessage()); }
import org.davison.data.jdbc.JDBCProvider; . . . DataProvider dp = new JDBCProvider();
In some cases code is written with dynamic dependencies between parts of the code by utilising Java ability to load and instantiate arbitrary classes. If not properly managed, this can cause run-time errors. This design can impart a performance penalty because of the extra levels of indirection. It can also prevent the compiler from detecting certain types of error.
有时候利用反射方式编写的代码,在加载和初始化的代码中产生了依赖关系。如果不恰当的处理,会引起运行时异常。这种方式由于引入了额外的间接性使得执行性能下降,另一方面,在编译期能够逃过一些类型错误。
Start with this code:
try { DataProvider dp = (DataProvider) Class.forName("org.davison.data.jdbc.JDBCProvider").newInstance(); } catch (IllegalAccessException iae) { // Convert exception to error to preseve the interface. // throw new IllegalAccessError(iae.getMessage()); } catch (InstantiationException ie) { // Convert exception to error to preseve the interface. // throw new InstantiationError(ie.getMessage()); } catch (ClassNotFoundException cnfe) { // Convert exception to error to preseve the interface. // throw new NoClassDefFoundError(cnfe.getMessage()); }We can remove the error handling code and simply instantiate the class.
移除异常处理代码,利用该类构造函数取代反射。
DataProvider dp = new JDBCProvider();
The final step is to add in the correct import statement
最后一步,添加Import语句。
import org.davison.data.jdbc.JDBCProvider; . . . DataProvider dp = new JDBCProvider();
Compile and test at this point as we have code that is complete.
When this is finished and all dependent classes are re-tested, the refactoring is complete.
Another way of creating compile time dependencies is to use class literals. This would still have the overhead of dynamic instantiation. I would not recommend this unless you have good reason; but here is the code converted to use this method.
另一种方式是利用Class进行构造。但依然会有开销。我不推荐此种方式,除非有好的原因。
try { DataProvider dp = (DataProvider) org.davison.data.jdbc.JDBCProvider.class.newInstance(); } catch (IllegalAccessException iae) { // Convert exception to error to preseve the interface. // throw new IllegalAccessError(iae.getMessage()); } catch (InstantiationException ie) { // Convert exception to error to preseve the interface. // throw new InstantiationError(ie.getMessage()); } catch (ClassNotFoundException cnfe) { // Convert exception to error to preseve the interface. // throw new NoClassDefFoundError(cnfe.getMessage()); }