5

私はこのプロジェクトに参加しており、かなりのレガシー コードを基に構築しています。ワイヤ経由で転送する必要がある 1 つの大きな Java Bean オブジェクトについて、特定の状況があります。したがって、私の最初の考えは、トリックを実行するために不変かつシリアライズ可能にすることでした。この時点で、いくつかの難しい選択に直面しています:-

  1. 理想的には、このクラスの不変でシリアル化可能なバージョンを自動的に生成する何らかの方法が必要です。このクラスを何らかの方法でリファクタリングまたは変更する範囲がありません。別の名前でクラスをコピーして貼り付ける必要があるのは本当に嫌いですか?

  2. 1つをあきらめたと仮定すると、つまり、実際に巨大なjavabeanクラスのコードを複製することを選択した場合でも、このクラスを不変にするために20〜25個のパラメーターを持つコンストラクターを作成する必要があるという不快な状況になります。コンストラクター注入以外にクラスを不変にするより良い方法は何ですか?

よろしくお願いいたします。

4

6 に答える 6

4

真に不変にするには、構築時にメンバーを初期化する必要があります。

これを実行し、コンストラクター内の巨大なパラメーターリストを回避する1つの方法(そして私はそれがきれいだとは言いません!)は、同じプロパティを持つ可変型を持つことです。「setters」を使用して、可変型のプロパティを一度に1つずつ設定してから、可変オブジェクトを単一の引数として不変型のコンストラクターに渡します。次に、不変オブジェクトは、プロパティを可変ソースからそれ自体の(final)メンバーにコピーします。

また、「効果的な不変性」を検討することもできます。つまり、システムによって不変性が強制されていない場合でも、初期化フェーズと使用フェーズを明確に分離するコーディング手法を使用します。結局のところ、シリアル化には不変性は必要ありません。

これをさらに一歩進めて、実装のプロパティを公開しないインターフェイスの実装を非表示にするラッパーを作成できます。ラッパーは、「実際の」実装に委任することによって、インターフェースのメソッドのみを実装します。実装からのセッターとゲッターはラッパーに存在しません。これにより、クライアントがインターフェイスから実装クラスに単純にダウンキャストしてプロパティを操作するのを防ぐことができます。

于 2009-04-15T20:01:24.397 に答える
4

Joshua Bloch の「Effective Java」は、単純な Builder オブジェクトを使用して、長いコンストラクタ引数リストを持つ複雑なオブジェクトを構築する Builder パターンを示しています。私はそれをお勧めします。

http://www.drdobbs.com/java/208403883;jsessionid=PJWS41F5DJ4QRQE1GHRSKH4ATMY32JVN?pgno=2

于 2010-03-24T21:51:16.433 に答える
1

ゲッターを含む単純な読み取り専用インターフェースはどうですか?

Bean クラスが独自のものである場合は、単純にインターフェイスを実装し、作成後にインターフェイスのみを使用します。

Bean クラスを制御できない場合は、すべてのメソッド呼び出しを Bean に委譲する呼び出しハンドラを使用して getter インターフェイスのプロキシを作成することにより、getter インターフェイスを作成して実装することもできます。

于 2010-03-24T21:59:53.233 に答える
1

20 ~ 25 個のプロパティは、特に中途半端なエディターを使用している場合は、1 回限りの場合には大きくありません。

不変バージョンを構築するときに既に可変インスタンスがある場合は、それをコンストラクターに渡すだけです。

本当に邪悪なハックになりたい場合は、変更可能なクラスまたはサブクラスを実装するためのシリアライズ可能なクラスjava.beansを作成するために使用します。あるいは、XML シリアライゼーション (Java シリアライゼーションで送信できる XML...) を使用することもできます。MapExternalizablejava.beans

于 2009-04-15T20:14:44.693 に答える
0

いくつかのアイデア:

保護されたセッターとファクトリメソッド 保護されたセッターメソッドを使用してBeanを定義し、同じパッケージ内で、すべてのパラメーターを受け取り、それらのセッターを呼び出すファクトリクラスを定義できます。Beanは、そのパッケージの外部では不変です。これを強制するには、エンドユーザーが同じパッケージに新しいクラスを作成できないように、必ずjarを封印してください。

注:JavaDude Beanアノテーションを使用して、作成を簡単にすることができます: http ://code.google.com/p/javadude/wiki/Annotations

例えば:

@Bean(writer=Access.PROTECTED, // all setXXX methods will be protected
    properties={
        @Property(name="name"),
        @Property(name="age", type=int.class)
    })
public class Person extends PersonGen {
}

Eclipseでのゲッターとコンストラクターの作成

Eclipseには、これを高速化するための優れたツールがいくつかあります。

  1. Beanクラスを作成します
  2. 必要なフィールドを追加します
  3. エディターウィンドウを右クリックします
  4. 「ソース」->「ゲッターとセッターの生成」を選択します
  5. 「ゲッターの選択」ボタンを押します
  6. [OK]を押します
  7. エディターウィンドウを右クリックします
  8. [ソース]->[フィールドからコンストラクターを生成]を選択します
  9. コンストラクターで必要なフィールドを選択して順序付けます
  10. [OK]を押します

不変性デコレータ

もう1つのアイデアは、getterとsetterを使用してBeanを定義することです(上記の手法を使用できますが、setterを含めることができます)。次に、getterのみを持つそのラッパークラスを作成できます。

于 2009-04-16T16:14:46.007 に答える
0

ステップ 1 : 新しいクラスを作成し、「大きな Java Bean オブジェクト」のインスタンス変数とまったく同じ名前のインスタンス変数を与えます。その新しいクラスには、不変にするためのセッター (ただし、ゲッターのみ) を含める必要はありません。

ステップ 2 : Apache Commons BeanUtils.copyPropertiesを使用して、すべてのプロパティ (つまり、インスタンス変数) を「大きな Java Bean オブジェクト」から新しいオブジェクトにコピーします。

于 2009-04-15T23:50:12.367 に答える