如何在没有instanceOf的情况下实现我的LayoutManager?

发布于 2024-07-16 02:53:18 字数 501 浏览 11 评论 0原文

对于我正在处理的特定布局,我需要制作自己的 LayoutManager

它将根据不同的类型来布局不同的组件:标签以一种方式,分隔符以另一种方式,其他所有内容以第三种方式。

如果我创建一个方法,我可以轻松实现这一点并确定不同类型组件的不同位置:

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

是否有更好的方法来做到这一点,而不使用 instanceOf

(不,我不必制作自己的 LayoutManager,但如果我这样做,事情就会变得非常容易;))

提前致谢

/B

For a certain layout that I'm working on, I need to make my own LayoutManager.

It will lay out different components depending on what type they are: Labels in one way, Separators in another way, and everything else in a third way.

I can easily implement this and to determine the different positions for different types of components, if I make a method:

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

Is there a better way to do this, without using instanceOf?

(And no, I don't HAVE to make my own LayoutManager, but it makes things extremely easier if i do ;) )

thanks in advance

/B

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

黑凤梨 2024-07-23 02:53:18

我还建议某种接口/子类解决方案来封装不同组件的不同布局计算。 我还会添加一些注册机制,以便灵活地应对未来的添加(如果您想为新组件类型实现另一个单独的行为)

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 类。

I'd also suggest some kind of interface/subclass solution for encapsulating the different layout calculations for different components. I also would add some registration mechanism in order to be flexible for future additions (if you want to implement another separate behaviour for new component types)

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);
  }
}

Now, you can register individual PositionCalculators for all of your components by putting

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

Of course, this solution might suffer from the following drawbacks:

  • It's probably slower than the original one.
  • It doesn't work with inherited classes: if you have a subclass from JLabel, you must register it separately. The solution could be adapted to this, but this would be at the cost of another performance loss...

On the other hand, the solution is pretty well extensible: You can define different layout behaviour without touching your MyLayoutManager class.

看轻我的陪伴 2024-07-23 02:53:18

您可能想要将信息添加到约束对象。 作为奖励/惩罚,您将获得额外的间接层。

我更喜欢使用布局管理器界面将组件添加到容器,而不是让容器将组件添加到布局管理器的默认方式。 这允许您以更自然的方式构造约束对象。 对于您的情况,您可以使用单独的方法来添加 JLabelJSeparator 等,这样您就不必重复信息并且可以有不同的参数。

You might want to add the information to the constraints object. As a bonus/penalty, you get an extra layer of indirection.

My preference is for layout manager interfaces to add components to the container, rather than the default way of having the container add components to the layout manager. That allows you to construct the constraints object in a more natural way. In your case, you can have separate methods for adding JLabel, JSeparator, etc., so that you don't have to repeat the information and can have differing arguments.

一笑百媚生 2024-07-23 02:53:18

唯一的其他实用方法是使用多态性并将函数calculatePositionForComponent()推送到组件接口/抽象类。 这又可以使用来自实际布局管理器的数据,然后返回尺寸。 在您的特定情况下使用此方法可能不切实际,具体取决于calculatePositionForComponent() 方法需要访问哪种类型的数据。

使用多个 instanceof if 子句时的一个技巧是使用 if-else if-else if-else 类型的样式。 然后根据实用性,将最明显的选择在比较层次结构中向上移动,以使 if 块更快。

The only other practical way is to use polymorphism and push the function calculatePositionForComponent() to the component interface/abstract class. This could in turn use data from the actual layout manager and then return the Dimensions. It might be impractical to use this approach in your particular case depending on what sort of data needs to be accessed by the calculatePositionForComponent() method.

A tip while working with multiple instanceof if clauses is to use if-else if-else if-else sort of styling. Then as per practicality move the most obvious choices up in the comparison hierarchy to make the if-block faster.

迷鸟归林 2024-07-23 02:53:18

看起来 instanceOf 可能是最直接的方法。 您不能使用方法重载,因为方法重载是在编译时决定的。 这意味着您不能只创建以下方法:

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

因为您仍然需要使用 instanceOf 和强制转换来获取在运行时调用的正确方法。

是的,使用 instanceOf 通常是一种代码味道,并且可能有更 OOP 的方法来执行此操作。 然而,对于这种特定类型的代码,我见过许多高级开发人员使用 instanceOf。 它出现在语言中是有原因的,而不仅仅是作为拐杖。 有时它是完成工作的最佳工具。 恕我直言,这是其中之一。

It looks like instanceOf may be the most straightforward way of doing this. You cannot use method overloading, as method overloading is decided at compile time. This means that you cannot just make the following methods:

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

because you'll still have to use instanceOf and casts to get the correct method to be invoked at runtime.

Yes, using instanceOf is usually a code smell, and there may be a more OOP way of doing this. However, for this specific kind of code, I've seen many advanced developers use instanceOf. It's in the langauge for a reason, not just as a crutch. There are times when it's the best tool for the job. IMHO, this is one of those times.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文