これは、非常に一般的な Java プログラミングの問題の例です。これは通常、Java Factory Design Pattern と呼ばれるものを使用して解決されます。次のリンクには、Factory パターンの簡単な説明があります - http://www.allapplabs.com/java_design_patterns/factory_pattern.htm
他にも参考になるデザインパターンがたくさんあります。それらについて読むと、多くの Java プログラマーが一般的に発生する問題をどのように解決しているかについての洞察が得られます。同じ著者が、 http://www.allapplabs.com/java_design_patterns/java_design_patterns.htmで、一般的な設計パターンのほとんどを説明しています。
さて、あなたの特定の問題について。まず、POI 作成者は Factory デザイン パターンを使用します。たとえば、次のコードを見てください。
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 の作成者は、ファイルの種類に応じて 2 つの非常に異なる実装を用意する必要があることは明らかです。
コードの内容など、多数の 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 ファイル用の 2 つのクラスを定義します。
// 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
}
}
単一の静的 create メソッドを使用して 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 ステートメントを 1 か所 (factory create メソッド) に配置しただけです。また、クラスのコードを記述し、create メソッドを簡単に変更するだけで、必要な数の DocExtractor 派生クラスを作成できることは明らかです。