あなたが想像していたよりも強力な列挙タイプ---ケース編
3758 ワード
先日、列挙機能の強い文章を紹介しました.何人かの友达が私に指摘してくれたが、単純な説明が直感的ではないケースはないと言った.確かに、ここではケース編を書いて、前回の文章について補足説明します.
このケースは、ゲームサーバのメッセージ識別器の簡略化です.ゲーム開発をしたことがあることはよく知られていますが、クライアントとサーバの間のインタラクションには多くのメッセージタイプを定義する必要があり、このメッセージタイプは絶えず拡張する必要があります.メッセージ識別器は、クライアントから送信されたメッセージ符号化に基づいて、ビジネスロジック層が処理するためにメッセージエンティティオブジェクトにカプセル化される.ここでは,この簡略化されたメッセージ識別器を用いて列挙されたアプリケーションを示す.(ここでは主に列挙の応用例のプレゼンテーションとして用いられていますが、コードが簡略化されているため、設計上の不適切な点が避けられませんので、ご了承ください)
メッセージエンティティークラスのインタフェース:
メッセージエンティティクラスの抽象クラス:
メッセージエンティティの実装クラス:
モジュール化管理のために、列挙タイプに対してインタフェースが抽出され、後でモジュールのメッセージが列挙クラスに登録され、これらの列挙クラスはこのインタフェースを実現する.
これは列挙クラスです.モジュールのメッセージが列挙クラスに登録されているモジュールの列挙クラスです.
最後にメッセージ識別器クラスです.
メッセージ識別器は、デコーダで使用されることが多い.デコーダは、データを受信した後、まずメッセージ符号化を読み出し、符号化呼び出し識別器に基づいてメッセージエンティティオブジェクトを取得し、メッセージエンティティオブジェクトを呼び出すreadData法により、クライアントデータをメッセージエンティティオブジェクトにユニークにする.
後でメッセージを拡張する場合は、メッセージエンティティクラスを作成し、列挙クラスに登録するだけです.:)
このケースは、ゲームサーバのメッセージ識別器の簡略化です.ゲーム開発をしたことがあることはよく知られていますが、クライアントとサーバの間のインタラクションには多くのメッセージタイプを定義する必要があり、このメッセージタイプは絶えず拡張する必要があります.メッセージ識別器は、クライアントから送信されたメッセージ符号化に基づいて、ビジネスロジック層が処理するためにメッセージエンティティオブジェクトにカプセル化される.ここでは,この簡略化されたメッセージ識別器を用いて列挙されたアプリケーションを示す.(ここでは主に列挙の応用例のプレゼンテーションとして用いられていますが、コードが簡略化されているため、設計上の不適切な点が避けられませんので、ご了承ください)
メッセージエンティティークラスのインタフェース:
public interface IMsg {
public void setMsgCode(int code);
public void execute();
public void readData(IoBuffer bufer);
public void writerData(IoBuffer bufer);
}
メッセージエンティティクラスの抽象クラス:
public abstract class AbstractMsg implements IMsg{
protected int msgCode;
public AbstractMsg(int msgCode){
this.msgCode = msgCode;
}
}
メッセージエンティティの実装クラス:
public class TestMsg extends AbstractMsg{
public TestMsg(int msgCode) {
super(msgCode);
}
private int data1;
private int data2;
@Override
public void setMsgCode(int code) {
this.msgCode = code;
}
@Override
public void execute() {
//
}
@Override
public void readData(IoBuffer bufer) {
this.data1 = bufer.getInt();
this.data2 = bufer.getInt();
}
@Override
public void writerData(IoBuffer bufer) {
}
}
モジュール化管理のために、列挙タイプに対してインタフェースが抽出され、後でモジュールのメッセージが列挙クラスに登録され、これらの列挙クラスはこのインタフェースを実現する.
public interface IMsgCodeClass {
public int getMsgCode();
public Class<? extends AbstractMsg> getMsgClass();
}
これは列挙クラスです.モジュールのメッセージが列挙クラスに登録されているモジュールの列挙クラスです.
public enum MsgCodeClassConstants implements IMsgCodeClass{
test(1001,TestMsg.class)//
;
private int msgCode;
private Class<? extends AbstractMsg> msgClass;
MsgCodeClassConstants(int msgCode,Class<? extends AbstractMsg> msgClass){
this.msgCode = msgCode;
this.msgClass = msgClass;
}
@Override
public int getMsgCode() {
return msgCode;
}
@Override
public Class<? extends AbstractMsg> getMsgClass() {
return msgClass;
}
}
最後にメッセージ識別器クラスです.
public class MsgRecogniser {
Map<Integer, Class<? extends AbstractMsg>> msges = new ConcurrentHashMap<Integer, Class<? extends AbstractMsg>>();
public void init(){
MsgCodeClassConstants[] contants = MsgCodeClassConstants.values();
for(int i=0;i<contants.length;i++){
msges.put(contants[i].getMsgCode(), contants[i].getMsgClass());
}
}
public IMsg getMsg(int msgCode){
IMsg msg = null;
Class clazz = msges.get(msgCode);
try {
Constructor constructor = clazz.getConstructor(int.class);
msg= (IMsg) constructor.newInstance(msgCode);
} catch (Exception e) {
e.printStackTrace();
}
return msg;
}
}
メッセージ識別器は、デコーダで使用されることが多い.デコーダは、データを受信した後、まずメッセージ符号化を読み出し、符号化呼び出し識別器に基づいてメッセージエンティティオブジェクトを取得し、メッセージエンティティオブジェクトを呼び出すreadData法により、クライアントデータをメッセージエンティティオブジェクトにユニークにする.
後でメッセージを拡張する場合は、メッセージエンティティクラスを作成し、列挙クラスに登録するだけです.:)