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