Я бы также предложил какое-то решение интерфейса / подкласса для инкапсуляции различных расчетов компоновки для разных компонентов. Я также добавил бы некоторый механизм регистрации, чтобы быть гибким для будущих дополнений (если вы хотите реализовать другое отдельное поведение для новых типов компонентов)
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);
}
}
Теперь вы можете зарегистрировать отдельные PositionCalculator для всех ваших компонентов, набрав
MyLayoutManager.registerPositionCalculator(JLabel.class, new JLabelCalculator());
MyLayoutManager.registerPositionCalculator(JRadioButton.class, new JRadioButtonCalculator());
// ...
Конечно, это решение может страдать от следующих недостатков:
- Это, вероятно, медленнее, чем оригинал.
- Он не работает с унаследованными классами: если у вас есть подкласс от JLabel, вы должны зарегистрировать его отдельно. Решение может быть адаптировано к этому, но это будет за счет другой потери производительности ...
С другой стороны, решение довольно хорошо расширяемое: вы можете определить другое поведение макета, не касаясь вашего класса MyLayoutManager.