对于我正在处理的特定布局,我需要制作自己的LayoutManager
。
它将根据它们的类型布置不同的组件:Label
以一种方式,分隔符以另一种方式,以及其他所有内容以第三种方式。
如果我制作方法,我可以很容易地实现这个并确定不同类型组件的不同位置:
private Dimension calculatePositionForComponent(Component component) {
if (component instanceOf JLabel)
...
if (component instanceOf JSeparator)
...
}
有没有更好的方法来执行此操作,而不使用instanceOf
?
(不,我不需要自己制作LayoutManager
,但如果我这样做会让事情变得非常容易;))
提前致谢
/ B
答案 0 :(得分: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);
}
}
现在,您可以通过
为所有组件注册单独的PositionCalculatorMyLayoutManager.registerPositionCalculator(JLabel.class, new JLabelCalculator());
MyLayoutManager.registerPositionCalculator(JRadioButton.class, new JRadioButtonCalculator());
// ...
当然,这种解决方案可能会遇到以下缺点:
另一方面,该解决方案具有很好的可扩展性:您可以在不触及MyLayoutManager类的情况下定义不同的布局行为。
答案 1 :(得分:1)
您可能希望将信息添加到约束对象。作为奖励/惩罚,你得到额外的间接层。
我的首选是布局管理器接口将组件添加到容器,而不是让容器向布局管理器添加组件的默认方式。这允许您以更自然的方式构造约束对象。在您的情况下,您可以使用单独的方法添加JLabel
,JSeparator
等,这样您就不必重复信息并且可以有不同的参数。
答案 2 :(得分:0)
唯一的另一种实用方法是使用多态并将函数calculatePositionForComponent()推送到组件接口/抽象类。这可以反过来使用来自实际布局管理器的数据,然后返回Dimensions。在您的特定情况下使用此方法可能是不切实际的,具体取决于calculatePositionForComponent()方法需要访问哪种数据。
使用多个instanceof if子句时的提示是使用if-else if-else if-else类型样式。然后根据实际情况,在比较层次结构中移动最明显的选择,以使if-block更快。
答案 3 :(得分:0)
看起来instanceOf
可能是最简单的方法。您不能使用方法重载,因为方法重载是在编译时决定的。这意味着您不能只使用以下方法:
private Dimension calculatePositionForComponent(JLabel component) {
....
}
private Dimension calculatePositionForComponent(JSeparator component) {
....
}
....
因为你仍然需要使用instanceOf
和强制转换才能获得在运行时调用的正确方法。
是的,使用instanceOf
通常是代码味道,并且可能有更多OOP方式来执行此操作。但是,对于这种特定类型的代码,我看到许多高级开发人员使用instanceOf
。它出于某种原因而不仅仅是作为一个拐杖。有时它是这项工作的最佳工具。恕我直言,这是其中一次。