Quantcast
Channel: CSDN博客推荐文章
Viewing all articles
Browse latest Browse all 35570

Convert Dynamic to Static Construction -- 动态到静态构造转换

$
0
0

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();

Motivation 动机

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.

有时候利用反射方式编写的代码,在加载和初始化的代码中产生了依赖关系。如果不恰当的处理,会引起运行时异常。这种方式由于引入了额外的间接性使得执行性能下降,另一方面,在编译期能够逃过一些类型错误。


Mechanics

  • Identify the places where the different classes are instantiated. If there is more than one place, you might like to make use of code consolidation refactorings to create one entry point.
  • 确定利用反射构造对象的地方。如果超出一个地方,你可能需要整合你的代码,使得多个地方变为一个地方。
  • You can remove the code that instantiates the classes using java.lang.reflect. We will instead call the constructors directly.
  • 你可以移除应用java.lang.reflect.的代码,以构造函数直接取代。
  • Replace the code that selects the name of the class with simpler code that simply returns a new instance.
  • 以简单的代码返回一个新实例替代掉利用反射构造对象的代码。
  • Add in import statements as required for the classes being constructed.
  • 添加Import,使得需要构造的类引入其中。
  • You are now ready to compile and test the code. Make sure that any dependant code is also tested properly.
  • 编译,测试。
  • The refactoring is complete.
  • 重构完成

Example

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());
   }

作者:changsheng1453052832 发表于2013-3-17 23:17:32 原文链接
阅读:42 评论:0 查看评论

Viewing all articles
Browse latest Browse all 35570

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>