gpt4 book ai didi

java - 如何抽象 poi 功能

转载 作者:行者123 更新时间:2023-11-29 08:06:24 40 4
gpt4 key购买 nike

我希望在我的程序中实现 apache-poi 的文本提取和稍后的摘要信息功能。也就是说,poi 对 .doc、docx、.xls 和 .xlsx 文件使用不同的库。

为了从调用 poi 的函数中隐藏这种复杂性,我制作了以下类和方法,我可以调用它来从 4 种文档类型中的任何一种中提取文本:

public class DocExtractor {
private WordExtractor w = null;
private XWPFWordExtractor wx = null;
private ExcelExtractor x = null;
private XSSFExcelExtractor xx = null;

public DocExtractor(File f){
String fileExtension = FilenameUtils.getExtension(f.toString());
if (fileExtension.equals("doc")){
try{
FileInputStream is = new FileInputStream(f.getAbsolutePath());
HWPFDocument doc = new HWPFDocument(is);
w = new WordExtractor(doc);
}
catch (Exception e){e.printStackTrace();}
}

...构造函数中还有 3 个“如果”

和方法:

    public String getText(){
String text ="";
if(this.w != null){
String[] texted = w.getParagraphText(); //for .doc
text = this.joiner(texted);
}

...还有更多“如果”

这有效,并隐藏了实现,

  DocExtractor dm = new DocExtractor(doFile);
text = dm.getText();

但我讨厌所有的“如果”。我忍不住想一定有更好的、完全不同的方法来做这件事,或者可能是一些多态的诡计……

这些私有(private)变量有点像以前尝试在这个类中遗留下来的,所以请随意将它们扔到您建议的任何解决方案中。

谢谢

最佳答案

这是一个非常常见的 Java 编程问题的示例。它通常使用所谓的 Java 工厂设计模式来解决。以下链接对工厂模式有一个很好的简单解释 - http://www.allapplabs.com/java_design_patterns/factory_pattern.htm

还有许多其他设计模式可供您引用。阅读它们将使您深入了解许多 Java 程序员是如何解决常见问题的。同一作者在 http://www.allapplabs.com/java_design_patterns/java_design_patterns.htm 解释了大多数常见的设计模式。

现在,关于您的具体问题。首先,POI 作者使用工厂设计模式。例如,看下面的代码:

Workbook wb1 = WorkbookFactory.create(new FileInputStream("myXlsFile.xls"));
Workbook wb2 = WorkbookFactory.create(new FileInputStream("myXlsxFile.xlsx"));
// this prints "wb1 class = org.apache.poi.xssf.usermodel.XSSFWorkbook"
System.out.println("wb1 class = " + wb1.getClass().getName());
// this prints "wb2 class = org.apache.poi.hssf.usermodel.HSSFWorkbook"
System.out.println("wb2 class = " + wb2.getClass().getName());

因此,作为 POI 的用户,无论您处理的是 xls 文件还是 xlsx 文件,您处理的都是具有相同属性和方法的同一个 Workbook 对象。然而,POI 的作者显然需要根据文件类型有两种截然不同的实现。

他们是如何在没有大量 if 语句的情况下做到这一点的,例如您的代码中的内容?我将重做您的示例以向您展示如何完成同样的事情。

您要做的第一件事是定义一个 DocExtractor 类,如下所示:

public abstract class DocExtractor {

// constructor
public DocExtractor(File f) {
poiFile = f;
}

// the getText method must be defined by all derived classes
public abstract String getText();

// this protected field is visible to all classes which extend DocExtractor
protected File poiFile;

}

我建议您将 DocExtractor 抽象化的原因是您不希望代码能够创建 DocExtractor 类。使 getText 方法抽象的原因是您要确保扩展 DocExtactor 的类将定义它们自己的 getText 版本。希望随着您继续阅读,这个推理会变得清晰。

您现在定义所谓的 DocExtractor 派生类(它们“扩展”DocExtractor)。在这个例子中,我将定义两个类,一个用于 doc 文件,一个用于 xls 文件。

// this handles doc files
public class DocExtractorDoc extends DocExtractor {

// constructor
public class DocExtractorDoc(File f) {
// this calls the DocExtractor constructor which has common code for all constructors
super(f);
// put code specific to the DocExtractorDoc constructor here
}

// concrete implementation of the getText method specific to doc files
public String getText() {
// getText code for doc files goes here
}
}

// this handles xls files
public class DocExtractorXls extends DocExtractor {

// constructor
public class DocExtractorXls(File f) {
// this calls the DocExtractor constructor which has common code for all constructors
super(f);
// put code specific to the DocExtractorXls constructor here
}

// concrete implementation of the getText method specific to xls files
public String getText() {
// getText code for xls files goes here
}
}

您现在使用单个静态创建方法定义 DocExtractorFactory 类:

public class DocExtractorFactory {

public static DocExtractor create(File f) {
// create the appropriate DocExtractor derived class based on the file extension
String extension = FilenameUtils.getExtension(f.getName());
if (extension.equals("doc") {
return new DocExtractorDoc(f);
} else if (extension.equals("xls") {
return new DocExtractorXls(f);
} else {
// error handling code here -- perhaps throw an exception
}
}
}

最后,这里是一些使用上述类的代码

// this actually creates a DocExtractorDoc object (but you don't care)
DocExtractor de1 = DocExtractorFactory.create(new File("myDocFile.doc"));
// this actually uses DocExtractorDoc.getText (but again you don't care)
String s1 = de1.getText();
// this actually creates a DocExtractorXls object
DocExtractor de2 = DocExtractorFactory.create(new File("myDocFile.xls"));
// this actually uses DocExtractorXls.getText
String s2 = de2.getText();

因此,我们基本上完成的只是将 if 语句放在一个地方,即工厂创建方法。显然,您只需编写类的代码并对创建方法进行简单更改,就可以根据需要创建尽可能多的 DocExtractor 派生类。

关于java - 如何抽象 poi 功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10944202/

40 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com