hehehe switch + enum był za miast bloku if/else i public static final.
teraz wredniejsza wersja i troszkę bardziej skomplikowana, wymaga pliku konfiguracyjnego .properties:
public class ObjectFactory {
private static PropertyUtil pu;
/**
* domyślna implementacja
* @return
* @throws InstantiationException
* @throws IllegalAccessException
* @throws ClassNotFoundException
*/
public static Cmd getCmd()
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Cmd) ( Class.forName( pu.get( "cmd.implementation" ) ).newInstance() );
}
/**
* implementacja wskazana przez uzytkownika
* @param key
* @return
* @throws InstantiationException
* @throws IllegalAccessException
* @throws ClassNotFoundException
*/
public static Cmd getCmd(String key)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Cmd) ( Class.forName( pu.get( key ) ).newInstance() );
}
}
Wystarczy podać klucz, a następnie z pliku konfiguracyjnego zostanie pobrana nazwa klasy i zwrócona jej instancja. Rozwiązanie jest o tyle skomplikowane, że wymusza użycie pliku zewnętrznego. Jako, że nie mogę użyć drugi raz metody, która przyjmuje String zatem muszę się decydować na konkretną implementację. No zostaje jeszcze zrobienie fabryki abstrakcyjnej:
public abstract class ObjectFactory {
protected static PropertyUtil pu;
/**
* domyślna implementacja
*
* @return
* @throws InstantiationException
* @throws IllegalAccessException
* @throws ClassNotFoundException
*/
public static Cmd getCmd()
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Cmd) ( Class.forName( pu.get( "cmd.implementation" ) ).newInstance() );
}
/**
* implementacja wskazana przez uzytkownika
*
* @param key
* @return
* @throws InstantiationException
* @throws IllegalAccessException
* @throws ClassNotFoundException
*/
public abstract Cmd getCmd( String key )
throws InstantiationException, IllegalAccessException, ClassNotFoundException;
}
class ObjectFactoryProp
extends ObjectFactory {
/**
* implementacja wskazana przez uzytkownika
*
* @param key
* @return
* @throws InstantiationException
* @throws IllegalAccessException
* @throws ClassNotFoundException
*/
public Cmd getCmd( String key )
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Cmd) ( Class.forName( pu.get( key ) ).newInstance() );
}
}
class ObjectFactoryKey
extends ObjectFactory {
/**
* implementacja wskazana przez uzytkownika
*
* @param key
* @return
* @throws InstantiationException
* @throws IllegalAccessException
* @throws ClassNotFoundException
*/
public Cmd getCmd( String key )
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Cmd) ( Class.forName( key ).newInstance() );
}
}
i dostarczenie dwóch różnych implementacji. Świetnie sprawdzi się z czymś w rodzaju Springa