Java:フレームワークの自作
ここでは、抽象クラスとリフレクションの二通りの方法で超簡易フレームワークを作成する方法を紹介します。
家で例えるなら、フレームワークは骨組みの部分です。言い換えると、共通部分です。同じ骨組みでも内装や外装の異なる家を複数建てたい場合がありますよね。 そういう場合は、あらかじめ共通の骨組みを作っておいて、内装や外装を後からカスタマイズできるようにしておくと便利です。 フレームワークには、更に、発生したイベントに応じて、ユーザが登録した関数(コールバック関数)を呼び出すイベント駆動の機構が備わっています。
下記の例では、Frameworkクラスが骨組みで、Modelクラスが内装や外装に相当します。MVCモデルで言えば、Frameworkクラスがコントローラで、Modelクラスがモデル、標準入出力がビューに相当します。
ライブラリとフレームワークの違い
ライブラリでは、ユーザ定義関数(user-defined function)がライブラリを呼び出すのに対し、 フレームワークでは、イベントが発生したときにフレームワークがユーザ定義関数を呼び出します。
1.抽象クラスを使ったフレームワーク
抽象クラスを使ったフレームワークはオーソドックスな方法ですが、弱点は、メソッド名やメソッド数がフレームワーク側で決まり、ユーザ側ではそれらを決定できないことです。 HttpServlet は抽象クラスを使って作られています。
package framework;
import java.util.Scanner;
public abstract class Framework {
protected Framework() {
Scanner scanner = new Scanner(System.in);
while (true) {
String event = scanner.nextLine();
switch (event) {
case "event1":
handle1();
break;
case "event2":
handle2();
break;
case "event3":
handle3();
break;
default:
System.err.println("exception");
}
}
}
protected abstract void handle1();
protected abstract void handle2();
protected abstract void handle3();
}
Frameworkクラスのコンパイル
set JAVA_HOME=D:\sdk\jdk set path=%path%;%JAVA_HOME%\bin javac D:/pkg/framework/*.java
次にユーザ側のプログラムです。Frameworkクラスを継承し、コールバック関数 handle1、handle2、handle3 を実装(登録)して Modelクラスを完成させます。
import framework.Framework;
class Model extends Framework {
protected void handle1() {
System.out.println("action1");
}
protected void handle2() {
System.out.println("action2");
}
protected void handle3() {
System.out.println("action3");
}
}
class Main {
public static void main(String... args) {
new Model();
}
}
ModelクラスとMainクラスのコンパイル
set JAVA_HOME=D:\sdk\jdk set path=%path%;%JAVA_HOME%\bin javac -cp D:/pkg *.java
Mainクラスの起動
set JAVA_HOME=D:\sdk\jdk set path=%path%;%JAVA_HOME%\bin java -cp .;D:/pkg Main
event1[Enter] action1 event2[Enter] action2 event3[Enter] action3
2.リフレクションを使ったフレームワーク
Javaのリフレクションは、実行時に、文字列(変数名や関数名)を通して、変数の読み書きや関数の呼び出しを行うための機能です。 この機能を使うと、switch文を使わずに、登録したメソッドをメソッド名(文字列)で呼び出すことができます。 リフレクションでフレームワークを作成すると、ユーザ側でメソッド名やメソッド数を自由に決めることができます。 Apache Struts はリフレクションを使って作られています。
package framework;
import java.lang.reflect.Method;
import java.util.Scanner;
public class Framework {
public Framework() {
Scanner scanner = new Scanner(System.in);
while (true) {
try {
String event = scanner.nextLine();
String stringClass = event.split(":", 0)[0];
String stringMethod = event.split(":", 0)[1];
Class<?> clazz = Class.forName(stringClass);
Method method = clazz.getMethod(stringMethod);
method.invoke(clazz.newInstance());
}
catch (ReflectiveOperationException e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
注)catch (Exception e) {} を外すと、捕捉できない例外が発生したときにループを抜けてしまいます。
次にユーザ側のプログラムです。メソッド名はユーザ側で自由に決めることができます。
public class Model {
public void handle1() {
System.out.println("action1");
}
public void handle2() {
System.out.println("action2");
}
public void handle3() {
System.out.println("action3");
}
}
import framework.Framework;
class Main {
public static void main(String... args) {
new Framework();
}
}
コンパイルや実行は、抽象クラスの場合と同じです。
Model:handle1[Enter] action1 Model:handle2[Enter] action2 Model:handle3[Enter] action3
参考サイト