“如果”语句与 OO 设计 - 2

发布于 2024-10-08 19:21:59 字数 848 浏览 3 评论 0原文

我遇到了类似的问题 “if”语句与 OO Design - 1 但略有不同。这是打开列表框的 onValueChange 弹出窗口(不同对象/弹出窗口)的问题

Popup1 p1; // different objects
Popup2 p2; // different objects
Popup3 p3;
...

listbox.add("p1");
listbox.add("p2");
listbox.add("p3");
...

listbox.addChangeHandler() {
    if(getSelectedItem().equals("p1")){
       p1 = new Popup1();
       p1.show();
    } else if() {...}
      ....
}

我不想写“if” if p1 then p1 = new Popup1(); p1.center();

我该如何处理这种情况?有什么设计模式吗?

这是我的解决方案,但成本太高,

map() {

    map.put("p1", new Popup1());
    map.put("p2", new Popup2());
    map.put("p3", new Popup3()); 
}

onValueChange() {
    map.get(selectedItem).show();
}

一个缺点是初始化所有弹出窗口。但仅当 valueChange 时才需要

I encountered similar problem “if” statement vs OO Design - 1 but it is slightly different. Here is the problem that open the popup (different objects/popups) onValueChange of listbox

Popup1 p1; // different objects
Popup2 p2; // different objects
Popup3 p3;
...

listbox.add("p1");
listbox.add("p2");
listbox.add("p3");
...

listbox.addChangeHandler() {
    if(getSelectedItem().equals("p1")){
       p1 = new Popup1();
       p1.show();
    } else if() {...}
      ....
}

I don't want to write "if" that if p1 then p1 = new Popup1(); p1.center();

How I can handle this situation? Any design-pattern?

Here is my solution but it is so costly

map() {

    map.put("p1", new Popup1());
    map.put("p2", new Popup2());
    map.put("p3", new Popup3()); 
}

onValueChange() {
    map.get(selectedItem).show();
}

One drawback is initialization all the popups. but it is require only when valueChange

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

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

发布评论

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

评论(6

暗喜 2024-10-15 19:21:59

好吧,如果 P1 和 P2 都实现相同的接口,那么

Popup1 implements Showable
Popup2 implements Showable

你可以简单地做

Showable showable = (Showable) listbox.getSelected();
showable.show();

Well, if P1 and P2 both implement the same interface, i.e

Popup1 implements Showable
Popup2 implements Showable

then you could simply do

Showable showable = (Showable) listbox.getSelected();
showable.show();
幽蝶幻影 2024-10-15 19:21:59

我同意尽可能利用公共基类,但您不能总是为可能需要在不同子类之间进行选择的每种用法向基类添加方法。

对于选择逻辑特定于一段代码的情况(例如将用户操作与对象(例如弹出窗口)匹配,并且您无法找到利用公共基类的方法),您的“地图”解决方案是一种不错的方法。

一个缺点是初始化所有弹出窗口。但仅当 valueChange 时才需要

您应该推迟实例化直到您需要它为止:

interface Showable {
    void show();
}
map() {

    map.put("p1", new Showable() { void show() { new Popup1().show(); } } );
    map.put("p2", new Showable() { void show() { new Popup2().show(); } } );
    map.put("p3", new Showable() { void show() { new Popup3().show(); } } ); 
}

onValueChange() {
    map.get(selectedItem).show();
}

匿名类是无状态的,因此如果您想提高效率,您可以创建匿名实例一次并重用它们。

I agree with leveraging the common base class when you can, but you can't always add a method to the base class for every usage that might call for selecting between different subclasses.

Your "map" solution is a decent approach for cases where the selection logic is specific to a piece of code, like matching user action to an object (e.g. popup), and you can't find a way to leverage the common base class.

One drawback is initialization all the popups. but it is require only when valueChange

You should defer the instantiation until you need it:

interface Showable {
    void show();
}
map() {

    map.put("p1", new Showable() { void show() { new Popup1().show(); } } );
    map.put("p2", new Showable() { void show() { new Popup2().show(); } } );
    map.put("p3", new Showable() { void show() { new Popup3().show(); } } ); 
}

onValueChange() {
    map.get(selectedItem).show();
}

The anonymous classes are stateless, so if you wanted to be extra efficient, you could create the anonymous instances once and reuse them.

沫雨熙 2024-10-15 19:21:59

是的,这种设计模式叫做多态性。您为所有 PopupX 类定义一个超类。在这个超类中,您定义了一个方法“onChange”。然后你在每个子类中实现这个方法。当您选择一个项目时,您可以定义超类对象的引用并调用“onChange”。

Yes, this design pattern is called polymorphism. You define a super class for all your PopupX classes. In this super class you define a method "onChange". Then you realize this method in each subclass. When you select an item, you define a reference on the superclass object and call "onChange".

甜警司 2024-10-15 19:21:59

如果确实存在三个不同的类 Popup1、Popup2、Popup3,那么它们应该继承一个公共基类(大概称为 Popup)或实现一个公共接口(如已经建议的那样)。但看来您需要一种方法将标识弹出窗口的字符串映射到弹出对象。听起来像是工厂模式的一个机会,它看起来像这样。

public class PopupFactory {
   private PopupFactory() { }
   public static Popup createPopup(String popupIdentifier) {
      if ("p1".equals(popupIdentifier)) return new Popup1();
      else if ("p2".equals(popupIdentifier)) return new Popup2();
      ...
   }

然后会像这样使用:

listbox.addChangeHandler() {
   Popup popup = PopupFactory.createPopup(getSelectedItem());
   popup.show();
   ....
}

If there really are three different classes Popup1, Popup2, Popup3, then they should either inherit from a common base class (presumably called Popup) or implement a common interface (as already suggested). But it appears you need a way to map strings identifying popups to popup objects. Sounds like an opportunity for factory pattern, which would look something like this.

public class PopupFactory {
   private PopupFactory() { }
   public static Popup createPopup(String popupIdentifier) {
      if ("p1".equals(popupIdentifier)) return new Popup1();
      else if ("p2".equals(popupIdentifier)) return new Popup2();
      ...
   }

And then would be used like:

listbox.addChangeHandler() {
   Popup popup = PopupFactory.createPopup(getSelectedItem());
   popup.show();
   ....
}
把昨日还给我 2024-10-15 19:21:59

你的“昂贵”解决方案对我来说似乎很好。更好的是,您可以从地图中填充列表框,因此:

for (String key: map.keyset())
    listbox.add(key);

当然,您可能希望键按特定顺序排列,在这种情况下,首先将它们添加到排序列表中。

ArrayList<String> list = new ArrayList<String>();
list.addAll(map.keySet());
Collections.sort(list);
for (String key: list)
    listbox.add(key);

Your "costly" solution seems just fine to me. Better yet, from your map you can populate the listbox, thus:

for (String key: map.keyset())
    listbox.add(key);

Of course you may want the keys in a particular order, in which case first add them to a sorted list.

ArrayList<String> list = new ArrayList<String>();
list.addAll(map.keySet());
Collections.sort(list);
for (String key: list)
    listbox.add(key);
_畞蕅 2024-10-15 19:21:59

不幸的是,鉴于限制,没有办法解决你提到的问题。

如果弹出窗口仅略有不同,则可以将它们实现为 1 个类,并具有定义弹出窗口类型的属性。

否则,最好将其封装在像@JST提到的工厂类中,这样丑陋的逻辑就只存在于一个地方。我不确定为什么您认为您的 map 解决方案成本高昂。

如果您想根据名称动态调用构造函数,则必须使用动态语言而不是 Java。

Unfortunately there's no way around what you mentioned given the constraints.

If the popups are only slightly different they could be implemented as 1 class with a property that defines what type of popup you have.

Otherwise the best you can do it encapsulate it in a factory class like @JST mentioned, that way the ugly logic exists in just one place. I'm not sure why you consider your map solution costly though.

If you want to dynamically invoke a constructor based on name, you're going to have to look at a dynamic language instead of Java.

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