Sin embargo, estoy totalmente de acuerdo en el punto de que "estático está mal usar aquí", entiendo algo de lo que intentas abordar aquí. Todavía el comportamiento de la instancia debería ser la forma de trabajar, pero si insistes, esto es lo que haría:
Comenzando con tu comentario "Necesito crear una instancia para obtener una cadena que sea realmente estática en el comportamiento"
No es del todo correcto. Si te ves bien, no estás cambiando el comportamiento de tu clase base, simplemente cambiando el parámetro para un método. En otras palabras, estás cambiando los datos, no el algoritmo.
La herencia es más útil cuando una nueva subclase quiere cambiar la forma en que funciona un método, si tan solo necesitas cambiar los "datos" que la clase utiliza para trabajar, probablemente un enfoque como este haría el truco.
class ModelBase {
// Initialize the queries
private static Map<String,String> selectMap = new HashMap<String,String>(); static {
selectMap.put("Album", "select field_1, field_2 from album");
selectMap.put("Artist", "select field_1, field_2 from artist");
selectMap.put("Track", "select field_1, field_2 from track");
}
// Finds all the objects for the specified class...
// Note: it is better to use "List" rather than "ArrayList" I'll explain this later.
public static List findAll(Class classToFind) {
String sql = getSelectSQL(classToFind);
results = execute(sql);
//etc...
return ....
}
// Return the correct select sql..
private static String getSelectSQL(Class classToFind){
String statement = tableMap.get(classToFind.getSimpleName());
if(statement == null) {
throw new IllegalArgumentException("Class " +
classToFind.getSimpleName + " is not mapped");
}
return statement;
}
}
Es decir, mapea todas las afirmaciones con un Mapa. El siguiente paso "obvio" es cargar el mapa desde un recurso externo, como un archivo de propiedades, o un xml o incluso (por qué no) una tabla de base de datos, para una mayor flexibilidad.
De esta forma puede mantener felices a sus clientes de la clase (y a usted), porque no necesita "crear una instancia" para hacer el trabajo.
// Client usage:
...
List albums = ModelBase.findAll(Album.class);
...
Otro enfoque es el de crear las instancias de atrás, y mantener su interfaz de cliente intacta durante el uso de los métodos de instancia, los métodos se marcan como "protegido" para evitar tener invocación externa. De un modo similar de la muestra anterior también se puede hacer esto
// Second option, instance used under the hood.
class ModelBase {
// Initialize the queries
private static Map<String,ModelBase> daoMap = new HashMap<String,ModelBase>(); static {
selectMap.put("Album", new AlbumModel());
selectMap.put("Artist", new ArtistModel());
selectMap.put("Track", new TrackModel());
}
// Finds all the objects for the specified class...
// Note: it is better to use "List" rather than "ArrayList" I'll explain this later.
public static List findAll(Class classToFind) {
String sql = getSelectSQL(classToFind);
results = execute(sql);
//etc...
return ....
}
// Return the correct select sql..
private static String getSelectSQL(Class classToFind){
ModelBase dao = tableMap.get(classToFind.getSimpleName());
if(statement == null) {
throw new IllegalArgumentException("Class " +
classToFind.getSimpleName + " is not mapped");
}
return dao.selectSql();
}
// Instance class to be overrided...
// this is "protected" ...
protected abstract String selectSql();
}
class AlbumModel extends ModelBase {
public String selectSql(){
return "select ... from album";
}
}
class ArtistModel extends ModelBase {
public String selectSql(){
return "select ... from artist";
}
}
class TrackModel extends ModelBase {
public String selectSql(){
return "select ... from track";
}
}
Y no es necesario cambiar el código de cliente, y todavía tienen el poder de polimorfismo.
// Client usage:
...
List albums = ModelBase.findAll(Album.class); // Does not know , behind the scenes you use instances.
...
espero que esto ayude.
Una nota final sobre el uso de List frente a ArrayList. Siempre es mejor programar en la interfaz que en la implementación, de esta manera usted hace que su código sea más flexible. Puede usar otra implementación de lista que sea más rápida o haga otra cosa, sin cambiar su código de cliente.
Estoy un poco confundido por qué estás escribiendo tu propio ORM cuando hay excelentes opciones como iBatis e Hibernate. Por cierto, me parece que estás tratando de hacer que un método estático de Java funcione como un método de clase Ruby. Si es así, no funcionará :( – Alan