とはいえ、「静的はここで使用するのは間違っている」という点には完全に同意しますが、ここで対処しようとしていることはある程度理解しています。それでもインスタンスの動作が機能するはずですが、これが私が行うことだと主張する場合:
あなたのコメントから始めて、「動作が本当に静的な文字列を取得するためだけに、そのインスタンスを作成する必要があります」
それは完全に正しいわけではありません。よく見ると、基本クラスの動作を変更しているのではなく、メソッドのパラメーターを変更しているだけです。つまり、アルゴリズムではなく、データを変更しています。
新しいサブクラスがメソッドの動作方法を変更したい場合、継承はより便利です。クラスが動作するために使用する「データ」を変更する必要がある場合は、おそらくこのようなアプローチがうまくいくでしょう。
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 );
...
もう 1 つの方法は、インスタンスを背後から作成し、インスタンス メソッドを使用している間はクライアント インターフェイスをそのまま維持することです。メソッドは、外部呼び出しを回避するために「保護」としてマークされます。前のサンプルと同様の方法で、これを行うこともできます
// 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 実装を使用するか、別のことを行うことができます。