第5章 デザインパターン適用の勘所
Authors:Agata Toshitaka
- M子:
-
「先輩できました(リスト2,リスト3)。
ユーティリティクラスを使ったらずいぶんすっきりしましたよ。
ユーティリティクラスの名前はUploadUtilにしました。」
リスト2 UploadUtil.java
public class UploadUtil {
private static final Log log = LogFactory.getLog(UploadUtil.class);
public static FileItem getFileItem(List fileItems, String name) {
for (Iterator iter = fileItems.iterator(); iter.hasNext();) {
FileItem item = (FileItem) iter.next();
if (item.getName().equals(name)) {
return item;
}
}
return null;
}
public static String getParameter(List fileItems, String name) {
return getFileItem(fileItems, name).getString();
}
| @ |
public static List parseRequest(
HttpServletRequest req, int maxFileSize)
throws FileUploadRuntimeException {
FileUpload fileUpload = new FileUpload();
fileUpload.setSizeMax(maxFileSize);
try {
return fileUpload.parseRequest(req);
| A | } catch (FileUploadException e) {
log.error(e.getMessage(), e);
throw new FileUploadRuntimeException(e);
}
|
}
|
}
リスト3 FileUploadServlet2.java
public class FileUploadServlet2 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();
| A |
if ("item.jpg".equals(filename)) {
ImageDao dao = new ImageDao();
dao.update(itemCode, filename, data);
} else if ("info.txt".equals(filename)) {
InfoDao dao = new InfoDao();
String info = new String(data, "Windows-31J");
dao.update(itemCode, info);
}
|
}
}
- O先輩:
-
「うん、かなりすっきりしたね。繰り返し似たようなコードを書いているなぁって思ったら、ユーティリティクラスにするとすっきりとした良いコードにできる場合が多いんだ。
別の場所からユーティリティクラスは再利用できるしね。」
- M子:
-
「再利用といえば、リスト3-@から呼び出しているリスト2-@のparseRequest()メソッドは工夫しましたよ。
ファイルサイズの上限を呼び出し側から渡せるようにしてるので、別の場所で上限が変わっても大丈夫です。
あと、100000ってわかりにくいってT美チャンに言われたんで、MAX_FILE_SIZEっていう定数にしました。」
- O先輩:
-
「素晴らしい・・・」
- M子:
-
(嬉しそうに)「実はもう一個工夫したのが、リスト2-Aの例外処理なんですよ。
実行時例外を使っちゃいました。
FileUploadExceptionが発生する場所で例外をキャッチして、実行時例外FileUploadRuntimeExceptionに変換して投げなおしています。
呼び出す側ではcatchが必要なくなっていい感じです。」
- O先輩:
-
「ちゃんと例外のロギングもやっているね、素晴らしい・・・」
- M子:
-
「でも、もう1つ気になっているところがあるんですよ。
仕様書には「最終的にはファイル名のパターンは30パターンになります」って書いてあるんですけど、増えたときにリスト3-Aのif文がすごく長くなっちゃいそうで。」
- O先輩:
-
「良いところに気づいたね。
この部分は「ファイルに対応した処理」共通のインタフェースを作って、「ファイル処理プラグイン」を作ればよいと思うんだ。
ファイル名に対応したプラグインをファクトリに作らせれば、if文をなくすこともできるはずだよ。
ちょっと一緒にやってみようか。」
- M子:
-
「プラグインかぁ。なんだかかっこいいですね。はい。お願いします。」
- O先輩:
-
「まずはif文の中身に注目してみよう。item.jpgとinfo.txtで処理に必要なデータってなんだろう?」
- M子:
-
「商品コードとファイル名、あとファイルの中身のbyte配列です。」
- O先輩:
-
「そうだね。その3つを引数にしたメソッドを持つインタフェースを作ってみよう。」
- M子:
-
「わかりました。やってみます。」