Skip to content

Instantly share code, notes, and snippets.

@fumokmm
Created July 3, 2012 21:55
Show Gist options
  • Save fumokmm/3043617 to your computer and use it in GitHub Desktop.
Save fumokmm/3043617 to your computer and use it in GitHub Desktop.
Javaで型トークンを利用したファクトリクラス
package fumokmm.test.factory;
import java.util.*;
import org.junit.*;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
public class FactoryTest {
static abstract class Alphabet {
abstract String whoAmI();
}
static class A extends Alphabet {
@Override String whoAmI() { return "I'm A!"; }
}
static class B extends Alphabet {
@Override String whoAmI() { return "I'm B!"; }
}
static class C extends Alphabet {
@Override String whoAmI() { return "I'm C!"; }
}
static interface Animal {}
static class Cat implements Animal {}
static class Dog implements Animal {}
static class Factory<T> {
private Map<Class<? extends T>, T> instanceMap =
new HashMap<Class<? extends T>, T>();
public <U extends T> U getOrCreate(Class<U> clazz) {
if (! instanceMap.containsKey(clazz)) {
try {
instanceMap.put(clazz, clazz.newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return clazz.cast(instanceMap.get(clazz));
}
}
// 以下テスト
Factory<Alphabet> factory;
@Before
public void setup() {
factory = new Factory<Alphabet>();
}
@Test
public void createするテスト() {
A a = factory.getOrCreate(A.class);
assertThat(a instanceof A, is(true));
B b = factory.getOrCreate(B.class);
assertThat(b instanceof B, is(true));
C c = factory.getOrCreate(C.class);
assertThat(c instanceof C, is(true));
}
@Test
public void AlphabetとしてCreateするテスト() {
Alphabet someAlp = factory.getOrCreate(A.class);
assertThat(someAlp.whoAmI(), is("I'm A!"));
assertThat(someAlp instanceof A, is(true));
someAlp = factory.getOrCreate(B.class);
assertThat(someAlp.whoAmI(), is("I'm B!"));
assertThat(someAlp instanceof B, is(true));
}
@Test
public void Factoryの使い分けのテスト() {
// Animal用のFactory
Factory<Animal> aniFactory = new Factory<Animal>();
aniFactory.getOrCreate(Cat.class);
aniFactory.getOrCreate(Dog.class);
//aniFactory.getOrCreate(A.class);
// => コンパイルエラー:aniFactoryは Animal を extends (implements) したクラスのみ生成可能
}
@Test
public void インスタンスは同じファクトリ内で使い回されるテスト() {
assertThat("最初はサイズ0", factory.instanceMap.size(), is(0));
A a1 = factory.getOrCreate(A.class);
assertThat("Aを生成&取得", factory.instanceMap.size(), is(1));
factory.getOrCreate(B.class);
assertThat("Bを生成&取得", factory.instanceMap.size(), is(2));
A a2 = factory.getOrCreate(A.class);
assertThat("Aは既に取得済みなので増えない", factory.instanceMap.size(), is(2));
assertSame("同じオブジェクトのはず", a1, a2);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment