受信内容によって処理クラスを選択するようなケースでは、リフレクションのClass.forNameを駆使することで、
受信したクラス名からインスタンスを動的に生成することができる。
これにより、IMessageを継承したクラスの増減をコードに反映しなくて済むようになるというメリットがある。
ただし、当然下記のデメリットが発生する。
・実行速度が低下する。
・実行時例外の頻度があがる。
・コードの視認性が低下する。
・パラメーターありコンストラクタによるインスタンス生成には対応していない。
よって、どちらを選択するかはメリット、デメリットのトレードオフになるが、
Javaではリフレクションの使用は基本的に非推奨であることから、
受信しうるメッセージ名と処理クラスを紐付けたマップを事前に作成しておくのがよい。
(といいつつ、そのマップの更新が面倒だからリフレクション使うわけだが・・・)
以下、Class.forNameを利用した動的生成のサンプルコード。
package reflec;
public class ForName {
/**
* @param args
*/
public static void main(String[] args) {
String className = "reflec.Hoge";
// String className = "reflec.Mosa"; // Mosaを生成する場合はこっち
IMessage msg = null;
try {
msg = (IMessage) Class.forName(className).newInstance();
} catch (InstantiationException e) { // by newInstance()
// インスタンス作成不可の場合(パラメーターなしのコンストラクタが存在しない場合)
e.printStackTrace();
} catch (IllegalAccessException e) { // by newInstance()
// 権限がないとき
e.printStackTrace();
} catch (ClassNotFoundException e) { // by Class.forName()
// 指定した名称のクラスが存在しなかったとき
e.printStackTrace();
}
msg.recv();
}
}
class Hoge implements IMessage {
@Override
public void recv() {
System.out.println("hoge desu.");
}
}
class Mosa implements IMessage {
@Override
public void recv() {
System.out.println("mosa desu.");
}
}
interface IMessage {
void recv();
}
実行結果は
hoge desu.
となる。
コメントを残す