博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
在软件开发中利用反射机制来减少包依赖
阅读量:6715 次
发布时间:2019-06-25

本文共 4320 字,大约阅读时间需要 14 分钟。

hot3.png

 是我以前写的一个开源软件,主要功能是“将markdown语法的文档内容,导出为word,pdf,HTML等的文件;也支持markdown转HTML文本”。

其中,导出为word文档,需要依赖,导出pdf需要依赖。其中,iText支持4.x版本和5.x版本。这里就涉及到一个问题,我还是举例子说明下。

如果用户只需要一个功能,导出word文档功能。那用户总不能为了这个功能,而引入一个无关的iText包吧。反之也是,用户要导出PDF功能,却需要引入POI包。

但是,一开始我的代码还真是这样,如果不引入,会导致ClassNotFound异常,致使编译不通过,无法使用。

设计上,我是通过一个工厂类,然后根据需要的文件名后缀,来生产不同的文档Builder。代码一开始是这么写的。

public class BuilderFactory{	public static Decorator build(String ext) {		DecoratorBuilder decoratorBuilder;		if(ext.equalsIgnoreCase("docx")){			decoratorBuilder = new DocxDecoratorBuilder();		}else if(ext.equalsIgnoreCase("doc")){			decoratorBuilder = new DocDecoratorBuilder();		}else if(ext.equalsIgnoreCase("pdf")){			if(itextVersion==PDF_ITEXT_5X){				decoratorBuilder = new PDFDecoratorBuilder5x();			}else{				decoratorBuilder = new PDFDecoratorBuilder4x();;			}		}else if(ext.equalsIgnoreCase("html") ||ext.equalsIgnoreCase("htm")){			decoratorBuilder = new HTMLDecoratorBuilder();		}else{			throw new RuntimeException("请确认输出的文档为docx,doc,pdf,html的文档格式");		}		Decorator decorator = decoratorBuilder.build();		return decorator;	}}

这么写很大的问题,就是这个BuilderFactory依赖于DocxDecoratorBuilder,DocDecoratorBuilder,PDFDecoratorBuilder5x,PDFDecoratorBuilder4x,HTMLDecoratorBuilder。而这几个Bulder又各自依赖于不同的第三方jar包。假设我没引入POI包,DocxDecoratorBuilder,DocDecoratorBuilder报错,BuilderFactory就编译不通过了。

于是,就导致了我们一开始说到的问题。

如果用户只需要一个功能,导出word文档功能。那用户总不能为了这个功能,而引入一个无关的iText包吧。反之也是,用户要导出PDF功能,却需要引入POI包。

而且,还有个问题,如果用户需要导出的是PDF文档,那我怎么知道用户用的是iText 4.x包还是iText 5.x包?

这时候是用Java的反射机制的好时机!先看改造后的代码:

public class BuilderFactory{	private static final int PDF_ITEXT_5X = 5;	private static final int PDF_ITEXT_4X = 4;	private static int itextVersion = PDF_ITEXT_4X;		/**	 * 检查iText的版本	 */	static{		String doc5x = "com.itextpdf.text.Document";//		String doc4x = "com.lowagie.text.Document";		try {			Class.forName(doc5x);			itextVersion = PDF_ITEXT_5X;		} catch (ClassNotFoundException e) {			itextVersion = PDF_ITEXT_4X;		}	}		private static DecoratorBuilder initDecoratorBuilder(String className){		try {			@SuppressWarnings("rawtypes")			Class clazz = Class.forName(className);			return (DecoratorBuilder)clazz.newInstance();		} catch (InstantiationException e) {			e.printStackTrace();		} catch (IllegalAccessException e) {			e.printStackTrace();		} catch (ClassNotFoundException e) {			e.printStackTrace();		}		return null;	}		private static final String DOC_BUILDER_CLASS_NAME = "net.oschina.md2.export.builder.DocDecoratorBuilder";	private static final String DOCX_BUILDER_CLASS_NAME = "net.oschina.md2.export.builder.DocxDecoratorBuilder";	private static final String PDF_4X_BUILDER_CLASS_NAME = "net.oschina.md2.export.builder.PDFDecoratorBuilder4x";	private static final String PDF_5X_BUILDER_CLASS_NAME = "net.oschina.md2.export.builder.PDFDecoratorBuilder5x";	private static final String HTML_BUILDER_CLASS_NAME = "net.oschina.md2.export.builder.HTMLDecoratorBuilder";		public static Decorator build(String ext) {		DecoratorBuilder decoratorBuilder;		if(ext.equalsIgnoreCase("docx")){			decoratorBuilder = initDecoratorBuilder(DOCX_BUILDER_CLASS_NAME);		}else if(ext.equalsIgnoreCase("doc")){			decoratorBuilder = initDecoratorBuilder(DOC_BUILDER_CLASS_NAME);		}else if(ext.equalsIgnoreCase("pdf")){			if(itextVersion==PDF_ITEXT_5X){				decoratorBuilder = initDecoratorBuilder(PDF_5X_BUILDER_CLASS_NAME);			}else{				decoratorBuilder = initDecoratorBuilder(PDF_4X_BUILDER_CLASS_NAME);			}		}else if(ext.equalsIgnoreCase("html") ||ext.equalsIgnoreCase("htm")){			decoratorBuilder = initDecoratorBuilder(HTML_BUILDER_CLASS_NAME);		}else{			throw new RuntimeException("请确认输出的文档为docx,doc,pdf,html的文档格式");		}		Decorator decorator = decoratorBuilder.build();		return decorator;	}	}

现在,代码里我们只是先定义了各个Builder实现的包路径,然后通过

Class clazz = Class.forName(className);

(DecoratorBuilder)clazz.newInstance();

来初始化Builder,这样就解决了BuilderFactory 依赖过重的问题。用户需要用什么功能,就只需要引入相应的jar包即可。如果用导出HTML功能或者markdown转HTML功能,甚至任何其它包都不需要。

新的代码还使用了个小技巧,来检查用户使用的iText版本问题。代码就是下面这段

static{		String doc5x = "com.itextpdf.text.Document";//		String doc4x = "com.lowagie.text.Document";		try {			Class.forName(doc5x);			itextVersion = PDF_ITEXT_5X;		} catch (ClassNotFoundException e) {			itextVersion = PDF_ITEXT_4X;		}	}

以上,就是本人在代码开发中,使用反射来减少包依赖的小技巧。希望对看到本文的你有所帮助:-)

对了,如果刚好有markdown转其它文档的功能,可以看下 这个小软件,谢谢~

转载于:https://my.oschina.net/cevin15/blog/700993

你可能感兴趣的文章
查看dll依赖项
查看>>
koa和egg项目webpack热更新实现
查看>>
ansible普通用户su切换问题
查看>>
2017.10.1
查看>>
P1965 转圈游戏
查看>>
洛谷——P1187 3D模型
查看>>
温度传感器,ds18b20
查看>>
总结从python2.7和python3.0的语法差异
查看>>
PSP(4.13——4.19)以及周记录
查看>>
ecshop为什么删不掉商品分类
查看>>
spark学习笔记
查看>>
bzoj1941[Sdoi2010]Hide and Seek
查看>>
IT兄弟连 Java Web教程 经典面试题2
查看>>
利用setTimeoutc处理javascript ajax请求超时
查看>>
三、Java基础工具(1)_常用类——字符串
查看>>
文献管理与信息分析》第二讲作业
查看>>
java 遍历arrayList的四种方法
查看>>
根据不同的产品id获得不同的下拉选项 (option传多值)
查看>>
css3新增属性:多列(column)
查看>>
redis 主从配置和集群配置
查看>>