2009-09-03 17 views
1

私は、さまざまな種類のバイナリパケットを送受信するネットワークアプリケーションを作成しています。できるだけ簡単に新しい種類のパケットをアプリケーションに追加しようとしています。バイナリ構造の読み書き:このコードを単純化するには?

今のところ、私はPacketクラスを作成しました。そして、私は異なる種類のパケットごとにそのサブクラスを作成します。しかし、それは見た目ほどきれいではありません。私はこのようなコードで終わった:

static class ItemDesc extends Packet { 
    public final int item_id; 
    public final int desc_type; 
    public final String filename; 
    public final String buf; 

    public ItemDesc(Type t, int item_id, int desc_type, String filename, String buf) { 
     super(t); // sets type for use in packet header 
     this.item_id = item_id; 
     this.desc_type = desc_type; 
     this.filename = filename; 
     this.buf = buf; 
    } 

    public ItemDesc(InputStream i) throws IOException { 
     super(i); // reads packet header and sets this.input 
     item_id = input.readInt(); 
     desc_type = input.readByte(); 
     filename = input.readStringWithLength(); 
     buf = input.readStringWithLength(); 
    } 

    public void writeTo(OutputStream o) throws IOException { 
     MyOutputStream dataOutput = new MyOutputStream(); 
     dataOutput.writeInt(item_id); 
     dataOutput.writeByte(desc_type); 
     dataOutput.writeStringWithLength(filename); 
     dataOutput.writeStringWithLength(buf); 
     super.write(dataOutput.toByteArray(), o); 
    } 
} 

このアプローチについて私が気になるのはコードの繰り返しです - 私はパケット構造を4回繰り返しています。私はこれを避けることがうれしいですが、私はそれを簡素化する合理的な方法を見ることができません。

私はすべての可能なフィールドタイプの辞書を作成し、このような新しいパケットタイプを定義するPythonで書いていた場合:

ItemDesc = [('item_id', 'int'), ('desc_type', 'byte'), ...] 

私は、任意の関数型言語に似た何かをすることができることとします。しかし、私はJavaにこのアプローチをとる方法を見ることができません。

(たぶん私はあまりにも杓子定規だ、または私は、コードを書き、関数型プログラミングと書き込みコードに慣れて、私は:)任意の繰り返しを避けることができ)

は、任意の提案のために事前にありがとうございます。

+0

非常によく見えます。私はあなたがそれをより少ないコードにすることができるとは思わない。 – ChaosPandion

答えて

1

私はあなたの現在のコードが良い解決策であることに同意します。繰り返しのビット(重複はしませんが)は、悪いことではありません、IMO。

あなたはより多くのpython-ようなソリューションを望んでいた場合は、可能性:

  1. は、反復処理の共通writeTo方法を使用して直列化を行い、オーダー保存マップ構造のいくつかの種類にItemDescのメンバーの属性を元に戻し地図。また、各属性にゲッターを追加し、既存のフィールドのすべての用途を置き換える必要があります。
  2. メンバ属性をPropertiesオブジェクトで置き換え、バイナリ書き込みの代わりにプロパティのシリアル化を使用します。
  3. Javaリフレクションを使用してメンバーの属性とその型にアクセスしてそれらをシリアライズする共通のwriteToメソッドを記述します。

すべての3つのケースで、コードは現在の「醜い」コードよりも遅く、複雑で潜在的に脆弱です。私はこれをしません。

0

私には大丈夫です。継承チェーンの上にあるパケットの '一般的な'部分のいくつかを抽象化したいので、それらを読む必要はありませんが、あなたのような形式を繰り返すのは理にかなっています。コンストラクタから生データを読み込み、ストリームから読み込んで、書き込む場合です。私はそれに何も間違いはないと思う。

0

私はあなたがJavaベースでこれを行うことができますが、多分あなたはctorsの1を再利用することができわからない:

public ItemDesc(InputStream i) throws IOException { 
    super(i); // reads packet header and sets this.input 

    this(input.readInt(), input.readByte(), input.readStringWithLength(), input.readStringWithLength()); 
} 

は構文があるかもしれないwhtever「これは」このクラスのctorのへの呼び出しを意味しました。

+0

これは問題を解決しません - 私はまだパケットを書くためにパケット構造を繰り返す必要があります。 – mik01aj

関連する問題