Convert Static to Dynamic Construction -- 静态到动态构造转换
来源:互联网 发布:软件陷阱 编辑:程序博客网 时间:2024/06/04 19:54
You have classes that have static compile time dependencies on classes that can only be built on a specific platform.
你有一些平台独立的静态编译时期的类
Make use of the java.lang.reflect to break the static dependency.
利用java反射打破静态依赖。
import org.davison.data.jdbc.JDBCProvider; . . . DataProvider dp = new JDBCProvider();
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()); }
Motivation
In some cases you have to provide drivers to provide different functionality depending on the situation. You might have classes that on a given platform need to access some sun.* classes to perform a specific function. For example a class to access WinHelp needs to get the window handle via the sun.awt.windows.WWindowPeer classes.
有时候你会根据情况提供不同功能的驱动程序。
There might also be the desire to only provide certian functionality to a given sub-set of users. This is the equivalent of being able to compile out code without having to alter the source or use pre-compilers.
你可能期望给予用户不同的功能子集,这就相当于不用修改源码或者预编译就能达到这种目的。
This method can be used with good effect with application frameworks where you do not know which class need to be used at compile time.
在应用程序框架中使用反射是一种的好的方式,譬如在编译期你不知道到底需要选择哪个类时。
Mechanics
- Identify the place 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.
- Make sure that there is a common interface and method of construction. Utilise Extract Interface or use Extract Superclass to create a suitable abstraction to work with.
- Replace the class selection process with one that instead selects for the string name of the class in question.
- Remove any import statements that refere the the classes being constructed.
- Add code in to load and instantiate the class. For more parameterised contructors, make use of the java.lang.reflect package.
- Deal with any excpetion generated.
- You are now ready to compile and test the code. Make sure that any dependant code is also tested properly.
- The refactoring is complete, but you should make sure that this run-time dependency is properly documented and that all developers know to instantiate the classes using the new or altered method.
Example
Start with this code:
import org.davison.data.jdbc.JDBCProvider; . . . DataProvider dp = new JDBCProvider();
First we have to change the selection code to return a class name rather than an actual instance. We can safely remove the import statement that referes to this class.
Class.forName("org.davison.data.jdbc.JDBCProvider")
We can now instantiate the class, in this simple case the constructor has no parameters, so we do not have to make use of the extended java.lang.reflect package.
DataProvider dp = (DataProvider) Class.forName("org.davison.data.jdbc.JDBCProvider").newInstance();
We now have to add the code to deal with the possible exception cases. Here I have chosen to convert them to the equivalent Java Errors in order to maintain the interface. If this is not required then simpler code is possible.
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()); }
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.
- Convert Dynamic to Static Construction -- 动态到静态构造转换
- Convert Static to Dynamic Construction -- 静态到动态构造转换
- 静态绑定(static-binding) 动态绑定(dynamic-binding)
- Static and Dynamic Testing (静态测试和动态测试)
- 静态(Static)、虚拟(Virtual)、动态(dynamic)方法区别
- Linux - 动态(Dynamic)与静态(Static)函数库
- 动态链接(dynamic link)与静态链接(static link)
- 静态库(Static Library)和动态框架(Dynamic Framework)
- convert dynmic page to static
- 静态连接(dynamic link)和动态连接(static link)初步理解
- Delphi静态(static)、虚拟(virtual)、动态(dynamic)或消息处理(message)
- 静态代理(static proxy)和动态代理(dynamic proxy)
- Delphi对象的方法能定义- 静态(static)、虚拟(virtual)、动态(dynamic)或消息处理(message)
- 在动态库(dynamic libraries)和静态库(static libraries)使用模板(template)
- 【转】Static library & dynamic library -- linux系统下的静态库与动态库
- php-fpm的静态static和动态dynamic执行方式比较
- 动态页面到静态页面的转换
- hive中简单介绍分区表(partition table),含动态分区(dynamic partition)与静态分区(static partition)
- Spring 注解总结
- STL中的make_heap、push_heap、pop_heap示例程序
- Linux压缩解压命令
- android 系统 makefile文件(Android.mk)组织结构
- malloc/free与new/delete的区别
- Convert Static to Dynamic Construction -- 静态到动态构造转换
- 最小生成树 prim
- APP支持不同的设备 之 支持不同版本的平台
- windows上用eclipse 开发django和第一个hello world
- JMeter2.9选择语言
- 图解HTTPS
- Struts2标签详解
- Android中常用的位图操作(View与Bitmap转化、圆角、灰化、提取Alpha、旋转、倒影、剪切……)
- 联合主键关联