虽然,我完全同意“在这里使用静态是错误的东西”这一点,我有点理解你在这里想要解决的问题。仍然实例行为应该是工作方式,但如果你坚持这是我会做的:
从您的评论开始“我需要创建它的一个实例只是为了获得一个行为上真正静态的字符串”
这并不完全正确。如果你看起来不错,你并没有改变基类的行为,只是改变了方法的参数。换句话说,您正在更改数据,而不是算法。
当一个新的子类想要改变一个方法的工作方式时,继承更有用,如果你只需要改变这个类用来工作的“数据”,那么这样的方法就可以了。
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;
}
}
也就是说,用一个 Map 映射所有语句。“显而易见”的下一步是从外部资源(例如属性文件、xml 甚至(为什么不)数据库表)加载地图,以获得额外的灵活性。
这样你就可以让你的班级客户(和你自己)开心,因为你不需要“创建一个实例”来完成这项工作。
// Client usage:
...
List albums = ModelBase.findAll( Album.class );
...
另一种方法是从后面创建实例,并在使用实例方法时保持客户端接口完整,这些方法被标记为“受保护”以避免外部调用。以与上一个示例类似的方式,您也可以执行此操作
// 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";
}
}
而且你不需要改变客户端代码,仍然拥有多态的力量。
// Client usage:
...
List albums = ModelBase.findAll( Album.class ); // Does not know , behind the scenes you use instances.
...
我希望这有帮助。
关于使用 List 与 ArrayList 的最后一点说明。对接口编程总是比对实现更好,这样你的代码就更灵活了。您可以使用另一个更快的 List 实现,或执行其他操作,而无需更改客户端代码。