1

私が取り組んでいる特定のレイアウトについては、自分で作成する必要がありLayoutManagerます。

タイプに応じて異なるコンポーネントをレイアウトしますLabel。1つの方法で、セパレーターを別の方法で、その他すべてを3番目の方法で配置します。

メソッドを作成すると、これを簡単に実装し、さまざまなタイプのコンポーネントのさまざまな位置を決定できます。

private Dimension calculatePositionForComponent(Component component) {
  if (component instanceOf JLabel)
     ...
  if (component instanceOf JSeparator)
     ...
}

使用せずにこれを行うためのより良い方法はありinstanceOfますか?

(いいえ、自分LayoutManagerで作成する必要はありませんが、作成すると非常に簡単になります;))

前もって感謝します

/ B

4

4 に答える 4

1

この情報を制約オブジェクトに追加することができます。ボーナス/ペナルティとして、間接的な追加レイヤーが得られます。

私の好みは、コンテナーにコンポーネントをレイアウト マネージャーに追加させるデフォルトの方法ではなく、レイアウト マネージャー インターフェイスがコンポーネントをコンテナーに追加することです。これにより、より自然な方法で制約オブジェクトを構築できます。あなたの場合、情報を繰り返す必要がなく、異なる引数を持つことができるようにJLabel、 、 などを追加するための個別のメソッドを持つことができます。JSeparator

于 2009-04-01T09:26:40.487 に答える
1

また、さまざまなコンポーネントのさまざまなレイアウト計算をカプセル化するための、ある種のインターフェイス/サブクラス ソリューションを提案します。また、将来の追加に柔軟に対応できるように、いくつかの登録メカニズムを追加します (新しいコンポーネント タイプに対して別の別の動作を実装する場合)。

public interface PositionCalculator {
  Dimension calculatePositionForComponent(MyLayoutManager manager, Component component);
}

class JLabelCalculator implements PositionCalculator {
  public Dimension calculatePositionForComponent(MyLayoutManager manager, Component component) {
    // ...
  }
}

class JRadioButtonPosCalculator impements PositionCalculator {
  public Dimension calculatePositionForComponent(MyLayoutManager manager, Component component) {
    // ...
  }
}

// More classes ...


class MyLayoutManager extends LayoutManager {
  private static HashMap<Class, PositionCalculator> calculators = new HashMap<Class, PositionCalculator>();
  public static registerPositionCalculator(Class c, PositionCalculator p) {
    calculators.put(c, p);
  }
  private static PositionCalculator defaultCalculator = new DefaultPositionCalculator(); // Not shown here ...
  // ...
  private Dimension calculatePositionForComponent(Component c) {
    PositionCalculator calc = calculators.get(c.getClass());
    if (calc == null)
      calc = defaultCalculator;
    return calc.calculatePositionForComponent(this, c);
  }
}

これで、すべてのコンポーネントに対して個々の PositionCalculators を登録できます。

MyLayoutManager.registerPositionCalculator(JLabel.class, new JLabelCalculator());
MyLayoutManager.registerPositionCalculator(JRadioButton.class, new JRadioButtonCalculator());
// ...

もちろん、このソリューションには次のような欠点があります。

  • おそらくオリジナルより遅いです。
  • 継承されたクラスでは機能しません。JLabel のサブクラスがある場合は、それを個別に登録する必要があります。ソリューションをこれに適応させることはできますが、これには別のパフォーマンスの損失が伴います...

一方、ソリューションは非常に拡張可能です。 MyLayoutManager クラスに触れることなく、さまざまなレイアウト動作を定義できます。

于 2009-04-01T07:18:47.627 に答える
0

他の唯一の実用的な方法は、ポリモーフィズムを使用して、関数calculatePositionForComponent()をコンポーネントインターフェイス/抽象クラスにプッシュすることです。これにより、実際のレイアウトマネージャーからのデータを使用して、ディメンションを返すことができます。calculatePositionForComponent()メソッドでアクセスする必要のあるデータの種類によっては、特定のケースでこのアプローチを使用するのは実用的でない場合があります。

複数のinstanceofif句を操作する際のヒントは、if-elseif-elseif-elseのようなスタイルを使用することです。次に、実用性に従って、最も明白な選択肢を比較階層の上位に移動して、ifブロックを高速化します。

于 2009-04-01T06:11:30.063 に答える
0

これinstanceOfを行う最も簡単な方法のようです。メソッドのオーバーロードはコンパイル時に決定されるため、メソッドのオーバーロードは使用できません。これは、次の方法だけを作成することはできないことを意味します。

private Dimension calculatePositionForComponent(JLabel component) {
    ....
}
private Dimension calculatePositionForComponent(JSeparator component) {
    ....
}
....

instanceOf実行時に呼び出される正しいメソッドを取得するには、とキャストを使用する必要があるためです。

はい、instanceOf通常、使用はコードの臭いであり、これを行うにはもっとOOPの方法があるかもしれません。ただし、この特定の種類のコードについては、多くの上級開発者がを使用しているのを見てきましたinstanceOf。それは単なる松葉杖としてではなく、理由のために言語にあります。それが仕事に最適なツールである場合があります。私見、これはその時の一つです。

于 2009-04-01T06:18:28.423 に答える