您的位置:首页 > 其它

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

2013-03-17 23:31 288 查看
RefactoringcontributedbyGerardM.Davison

Youhaveclassesthathavestaticcompiletimedependenciesonclassesthatcanonlybebuiltonaspecificplatform.

你有一些平台独立的静态编译时期的类

Makeuseofthejava.lang.reflecttobreakthestaticdependency.

利用java反射打破静态依赖。
importorg.davison.data.jdbc.JDBCProvider;

.
.
.

DataProviderdp=newJDBCProvider();




try
{
DataProviderdp=(DataProvider)
Class.forName("org.davison.data.jdbc.JDBCProvider").newInstance();
}
catch(IllegalAccessExceptioniae)
{
//Convertexceptiontoerrortopresevetheinterface.
//

thrownewIllegalAccessError(iae.getMessage());
}
catch(InstantiationExceptionie)
{
//Convertexceptiontoerrortopresevetheinterface.
//

thrownewInstantiationError(ie.getMessage());
}
catch(ClassNotFoundExceptioncnfe)
{
//Convertexceptiontoerrortopresevetheinterface.
//

thrownewNoClassDefFoundError(cnfe.getMessage());
}


Motivation

Insomecasesyouhavetoprovidedriverstoprovidedifferentfunctionalitydependingonthesituation.Youmighthaveclassesthatonagivenplatformneedtoaccesssomesun.*classestoperformaspecificfunction.
ForexampleaclasstoaccessWinHelpneedstogetthewindowhandleviathesun.awt.windows.WWindowPeerclasses.
有时候你会根据情况提供不同功能的驱动程序。
Theremightalsobethedesiretoonlyprovidecertianfunctionalitytoagivensub-setofusers.Thisistheequivalentofbeingabletocompileoutcodewithouthavingtoalterthesourceorusepre-compilers.
你可能期望给予用户不同的功能子集,这就相当于不用修改源码或者预编译就能达到这种目的。
Thismethodcanbeusedwithgoodeffectwithapplicationframeworkswhereyoudonotknowwhichclassneedtobeusedatcompiletime.
在应用程序框架中使用反射是一种的好的方式,譬如在编译期你不知道到底需要选择哪个类时。

Mechanics

Identifytheplacewherethedifferentclassesareinstantiated.Ifthereismorethanoneplace,youmightliketomakeuseofcodeconsolidationrefactoringstocreateoneentrypoint.
Makesurethatthereisacommoninterfaceandmethodofconstruction.UtiliseExtractInterfaceoruseExtractSuperclasstocreateasuitableabstractiontoworkwith.
Replacetheclassselectionprocesswithonethatinsteadselectsforthestringnameoftheclassinquestion.
Removeanyimportstatementsthatreferethetheclassesbeingconstructed.
Addcodeintoloadandinstantiatetheclass.Formoreparameterisedcontructors,makeuseofthejava.lang.reflectpackage.
Dealwithanyexcpetiongenerated.
Youarenowreadytocompileandtestthecode.Makesurethatanydependantcodeisalsotestedproperly.
Therefactoringiscomplete,butyoushouldmakesurethatthisrun-timedependencyisproperlydocumentedandthatalldevelopersknowtoinstantiatetheclassesusingtheneworalteredmethod.

Example

Startwiththiscode:
importorg.davison.data.jdbc.JDBCProvider;

.
.
.

DataProviderdp=newJDBCProvider();


Firstwehavetochangetheselectioncodetoreturnaclassnameratherthananactualinstance.Wecansafelyremovetheimportstatementthatreferestothisclass.
Class.forName("org.davison.data.jdbc.JDBCProvider")


Wecannowinstantiatetheclass,inthissimplecasetheconstructorhasnoparameters,sowedonothavetomakeuseoftheextendedjava.lang.reflectpackage.
DataProviderdp=(DataProvider)
Class.forName("org.davison.data.jdbc.JDBCProvider").newInstance();


Wenowhavetoaddthecodetodealwiththepossibleexceptioncases.HereIhavechosentoconvertthemtotheequivalentJavaErrorsinordertomaintaintheinterface.Ifthisisnotrequiredthensimplercodeis
possible.
try
{
DataProviderdp=(DataProvider)
Class.forName("org.davison.data.jdbc.JDBCProvider").newInstance();
}
catch(IllegalAccessExceptioniae)
{
//Convertexceptiontoerrortopresevetheinterface.
//

thrownewIllegalAccessError(iae.getMessage());
}
catch(InstantiationExceptionie)
{
//Convertexceptiontoerrortopresevetheinterface.
//

thrownewInstantiationError(ie.getMessage());
}
catch(ClassNotFoundExceptioncnfe)
{
//Convertexceptiontoerrortopresevetheinterface.
//

thrownewNoClassDefFoundError(cnfe.getMessage());
}


Compileandtestatthispointaswehavecodethatiscomplete.
Whenthisisfinishedandalldependentclassesarere-tested,therefactoringiscomplete.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  重构 refactoring
相关文章推荐