第1章
はじめてのデザインパターン  

第2章
逆引きカタログ ロジック編

第3章
逆引きカタログ J2EE編

第4章
逆引きカタログ その他

第5章
デザインパターン適用の勘所

第5章 デザインパターン適用の勘所

Authors:Agata Toshitaka

動的にプラグインを生成するファクトリ

図5 サンプルのクラス図(その4)
O先輩:
「完成したFilePluginFactoryはこんな感じだよ(リスト8,リスト9,リスト10)。(ファクトリパターン参照)」

リスト8 FilePlugin.java
/**
 * FilePlugin生成クラスです。
 */
public class FilePluginFactory {
	/** 唯一のインスタンスです。*/
	private static FilePluginFactory instance = new FilePluginFactory();
	/** プロパティファイルを読み込みます。*/
	private ResourceBundle resource = ResourceBundle.getBundle("plugin");
	/**
	 * コンストラクタ(インスタンス化禁止)です。
	 */
	private FilePluginFactory() {
	}
	/**
	 * インスタンスを取得します。
	 */
	public static FilePluginFactory getInstance() {
		return instance;
	}
@
	/**
	 * ファイル名を元にプラグインを取得します。
	 */
	public FilePlugin getPlugin(String filename) {
		try {
			String className = resource.getString(filename);
			Class c Class.forName(className);
			return (FilePlugin) c.newInstance();
		} catch (Exception e) {
			throw new FilePluginFactoryRuntimeException(e);
		}
	}
}

リスト9 FileUploadServlet4.java
/**
 * ファイルアップロードサーブレット(ファクトリの使用)です。
 */
public class FileUploadServlet4 extends HttpServlet {
	/** ファイルサイズの上限です。 */
	private static final int MAX_FILE_SIZE = 1000000;
	protected void doPost(HttpServletRequest req, HttpServletResponse res)
				throws ServletException, IOException {
		// マルチパートデータを取得
		List fileItems = UploadUtil.parseRequest(req, MAX_FILE_SIZE);

		// 商品コードの取得
		String itemCode = UploadUtil.getParameter(fileItems, "code");

		// アップロードされたファイルの処理
		FileItem item = UploadUtil.getFileItem(fileItems, "file");
		String filename = item.getName();
		byte[] data = item.get();

		// ファクトリでファイル処理プラグインを生成
		FilePluginFactory factory = FilePluginFactory.getInstance();
		FilePlugin plugin = factory.getPlugin(filename);
		plugin.execute(itemCode, filename, data);
	}
}

リスト10 plugin.properties
item.jpg=example.part3.ImageFilePlugin
info.txt=example.part3.InfoFilePlugin
M子:
「if文がなくなりましたね。」
O先輩:
リスト8-@を見てごらん。 リストプロパティファイルからファイル名をキーにファイル処理プラグインのクラス名を取得して、Class.forNameで取得したClassオブジェクトをnewInstance()メソッドで生成しているんだよ。 これは動的にクラスを生成したいときの基本的なパターンだから覚えておくと便利だよ。」
M子:
「プラグインのクラス名はplugin.propertiesにファイル名とペアで書くんですね。 これなら、ファイル名のパターンが増えても、plugin.properitesに設定を追加して、FilePluginインタフェースを実装したクラスを1個書けば終わりですね。 どんなに増えても、永久にif文は出てきませんね。ところで、何でシングルトンパターンを使っているんですか?」
O先輩:
「このファクトリのインスタンスはシステムで1個あればよいからね。 それにシングルトンパターンにしておけば、「プラグインの生成は1回目のみ、2回目以降はキャッシュしたプラグインを返す」といったことも簡単にできるだ。」
M子:
「そういう目的があったんですね。 クラス図を見て思ったんですけど、ファクトリパターンを使うと登場するクラスが増えるし、複雑な印象を受けますね。 ファクトリパターンにするか、if文でそのままにするか悩むところですねぇ。 最初から「ファクトリパターンを使おう!」ってなかなか思いつきそうにないですよ。」
O先輩:
「そうだね。デザインパターンを学習し始めたころはそういう疑問がよく起きると思うんだ。 確かにファクトリパターンを使うと複雑になるし、あとからファイル処理のパターンが増えなかったら、ファクトリパターンにするメリットはあんまりないだろうね。 最初の段階ではif文で処理しておいたほうがシンプルで良いかもね。似たような2個目のパターンが出たとき、不吉な匂いを感じたときにデザインパターンの適用を検討したほうが、誤用も少ないし効果的なことが多いんだ。 いろいろ試行錯誤していくなかで、デザインパターンのさじ加減やコストと効果とのトレードオフを知ることが大事だと思うよ。」
M子:
「勉強になりました。ありがとうございます。今日はなんだか、先輩がかっこよく見えましたよ。」
O先輩:
(照れる)
TOP