俺ルールだ!@JAVA
研究用にJavaのコーディングしてたら、疲れてきたのでブログにエントリでも書いてます。
前置きですが、自分、基本的にデザインパターン(正確には巷で使われているデザインパターンの中身)が嫌いです。
理屈っぽすぎて、理解しがたいしコードが汚くなるし・・・orz
というわけで、最近、俺ルールなデザインパターンを構築しつつありますw
あと、俺ルール支援クラスライブラリも構築していますw
イベント駆動のプログラミングをするために、デザインパターンではObserver パターンを用いることになります。
このパターン、あまり好きになれません(´・ω・`;)
なぜなら、イベント駆動中にハンドラの変更が行われることを想定した設計になると、クラス毎に複雑な設計が必要になるからです。
単純にリストにリスナ突っ込んで、for-each で回すだけなら簡単なんですけどね・・・これやるとバグの温床になるので。
正直、イベント処理は言語レベルで対応しておいて欲しいと思うのですが・・・まあ、ないものねだりをしてもしかたないので、C#の event 修飾子 を模倣した Event<T> クラスを作ってみました。
-
package ncommon;
-
-
import java.util.LinkedList;
-
import java.util.List;
-
-
/**
-
* イベントを管理するクラス。
-
* @author naou
-
*/
-
public class Event<t> {
-
private List</t><t> handlers = new LinkedList</t><t>();
-
private List</t><t> copyHandlers = new LinkedList</t><t>();
-
private boolean changed = false;
-
-
/**
-
* イベントハンドラを追加する。
-
* @param handler
-
*/
-
public void addHandler(T handler){
-
handlers.add(handler);
-
changed = true;
-
}
-
-
/**
-
* イベントハンドラを削除する。
-
* @param handler
-
*/
-
public void removeHandler(T handler){
-
handlers.remove(handler);
-
changed = true;
-
}
-
-
/**
-
* イベントコレクションを取得する。
-
* @return
-
*/
-
public List</t><t> getHandlers(){
-
if( changed ){
-
copyHandlers = new LinkedList</t><t>(handlers);
-
}
-
return copyHandlers;
-
}
-
}
handlers に対して、add/removeHander を行い、getHandlers を呼び出す際に、その複製を作るようにしています。
一見すると無駄な処理のようですが、コレは必要な処理なのです。
こうしないと、イベントハンドラ内でイベントを削除するとエラーが起きるんです^q^;
イベントハンドラリストに対して、ループ(for-each)してる祭に、イベントを追加及び削除すると、ループがおかしくなってしまうという罠です。
後は、イベントを実装したいクラスで、
こんな感じでイベント実装します。
ここでイベント発生元オブジェクトを sender として第一引数に指定するようにしています(C#の受け売り・・・w)
変数名は event・・・、イベント取得ゲッターは event ではじめるという、まさに俺ルールですwww
こうすれば、あとは任意の場所で、
ってな感じで、イベントの内容を実装できます☆
あとついでに、Box<T>クラスを作ってみました。イメージとしてはポインタですね。
C# でいうところの out 修飾子代わりだったり、hoge == null ? default : hoge の代わりだったり、同期処理の支援のためだったりと、このクラス、何かと役立ちそうですw
-
package ncommon;
-
-
/**
-
*
-
* @author naou
-
*/
-
public class Box</t><t> {
-
private T object = null;
-
-
}
-
-
this.object = object;
-
}
-
-
public void clear(){
-
set(null);
-
}
-
-
public boolean isNull(){
-
return object == null;
-
}
-
-
/**
-
* @return the object
-
*/
-
public T get() {
-
return object;
-
}
-
-
public T get(T defaultValue){
-
if( isNull() ){
-
return defaultValue;
-
}
-
else{
-
return get();
-
}
-
}
-
-
/**
-
* @param object the object to set
-
*/
-
public void set(T object) {
-
this.object = object;
-
}
-
-
@Override
-
-
if( object == null ){
-
return b.isNull();
-
}
-
else{
-
return object.equals(b.get());
-
}
-
}else{
-
return false;
-
}
-
}
-
-
@Override
-
public int hashCode() {
-
int hash = 7;
-
hash = 89 * hash + (this.object != null ? this.object.hashCode() : 0);
-
return hash;
-
}
-
}
あとは、変数の設定が行われるたびにイベントを発生する EventedBox( extends Box ) とか、一行ごとにReadLine/WriteLine イベントを発生する EventedReader/EventedWriter 等など・・・便利そうなクラスを色々作っています。
あとは、ロガーとかも、WriteLog イベントを実装して、任意のログ出力処理を容易に書けるようにしています。
前に日記に書いた XmlDataDocument クラスをフルスクラッチして、XData クラスも作りました。
バグもつぶして、前よりも簡潔にアノテーションを指定できるようにしました。
これで、任意のXMLとJavaクラスのマッピングができるようになりました☆
Webアプリケーションとかで、XMLでデータを受け取った時に、Javaのオブジェクトにマッピングするといった事ができるようになりました。
XDesirialized を実装することで、デシリアライズした際に、妥当性を検証することもできます。
このクラスについては、いつかまたエントリでも書きます(`・ω・´)b