Saturday, June 27, 2015

Generics related design patterns: part I

Generics, introduced in Java 6, is one of the powerful features in Java to help developer to better design class and method, enabling type safety and compiling time check.

Here I introduced couple useful generics related design patterns.

1. typesafe hetergenous map, as described in book "Effective Java"

Mostly of time map contains certain type of keys and values, unless you create object as key or values, but if you do that, you lose the control of type checking. Using class literal introduced Java 5, we can create typesafe map. Here is the implementation:


/*
 * Typesafe container pattern
 */
public class TypeContainer {
Map<Class<?>, Object> map = new HashMap<Class<?>, Object>();
public <T> void put(Class<T> key, T instance){
map.put(key, instance);
}
public <T> T get(Class<T> key){
return key.cast(map.get(key));
}
}

2. Generified singleton pattern

We know the singleton holder pattern which is thread-safe way to create singleton. So how we can create generified singleton?

The idea is to created a typesafe container to hold all of the potential singleton instances. Note this is not a clean way.

/* 
 * generic singleton pattern
 */
public final static class Singleton<T> {
private Singleton(){}
public Singleton<T> getInstance(Class<T> type){

        // check if type is supported if does then return the singleton
return (Singleton<T>)(SingeltonHolder.store.get(type));
}
private final static class SingeltonHolder {
private static final Map<Class<?>, Singleton> store = new HashMap<Class<?>, Singleton>(){{
put(String.class, new Singleton<String>());
put(Integer.class, new Singleton<Integer>());
                        //add all of the supported types here
}};
}
}

3. Generic singleton factory pattern

/*
 * generic singleton factory pattern 
 */
public interface MyInterface<T> {
   T doSomthing(T arg);
}

public static class GenericFactory {
public static <T> MyInterface<T> getImpl() {
return (MyInterface<T>)IMPL;
}

/* here we only need one generic implementation */
private static final MyInterface<Object> IMPL = new MyInterface<Object>() {
@Override
public Object doSomthing(Object arg) {
return arg;
}
};
}






No comments:

Post a Comment