【generics】generic singleton factory
以前、generics では実行時に型情報がなくなることを紹介しました。
これを singleton とうまく合わせると、任意の型を扱える singleton を定義できます。
手順
- generic なインターフェースを作成する。
- generic なインターフェースを返すファクトリクラスを作成する。
generic な singleton を factory で提供することから、そのまま”generic singleton factory”というパターン名がついています。
(Effective Java 2nd edition - P131)
以下、具体例を示します。
(1)generic なインターフェース
ひとまず、こんなインターフェースを定義するとして下さい。
public interface Viewer{ /** * 引数を表示する。 * * @param t 表示する値 */ void view(T t); }
(2)ファクトリクラス
public class ViewerFactory { /** * Viewer の singleton。 * * 任意の型を扱えるようにするため、 * type parameter に Object を指定。 * 他は、通常の singleton と同じ。 */ private static final Viewer VIEWER = new Viewer() { public void view(Object obj) { System.out.println(obj); } }; /** * Viewer の singleton を返す。 * * 任意の type parameter を指定できるように定義。 * 他は、通常の singleton と同じ。 * * ちなみに、Viewer が immutable かつ stateless であること、 * および任意の型を取り扱えることから、 * 型の安全性は保障できる。 * そのため、キャスト時の警告は抑制して問題ない。 */ @SuppressWarnings("unchecked") public staticViewer getViewer() { return (Viewer ) VIEWER; } }
(3)検証用のテストコード
public void testViewerFactory() { // type inference なので、 // 左辺のみ type parameter を指定すればよい。 ViewerstringViewer = ViewerFactory.getViewer(); Viewer intViewer = ViewerFactory.getViewer(); // singletonであることの確認 assertSame( stringViewer, intViewer); // Viewer 自体の動作確認 String stringArray = new String {"are", "kore", "sore"}; int intArray = new int {12, 34, 56}; // キャストが不要! for (String str : stringArray) { stringViewer.view(str); } for (int i : intArray) { intViewer.view(i); } }
実行結果は、以下のようになります。
are
kore
sore
12
34
56