“if”声明与OO设计 - 2

时间:2010-12-21 16:37:42

标签: java design-patterns if-statement

我遇到了类似问题“if” statement vs 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() {...}
      ....
}

如果p1然后p1 = new Popup1(); p1.center();

,我不想写“if”

我如何处理这种情况?任何设计模式?

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

map() {

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

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

一个缺点是初始化所有弹出窗口。但只有在valueChange

时才需要

6 个答案:

答案 0 :(得分:1)

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

Popup1 implements Showable
Popup2 implements Showable

然后你可以简单地做

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

如果确实有三个不同的类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();
   ....
}

答案 3 :(得分:0)

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

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

  

一个缺点是初始化所有弹出窗口。但只有在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();
}

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

答案 4 :(得分:0)

您的“昂贵”解决方案对我来说似乎没问题。更好的是,您可以从地图中填充列表框,这样:

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

答案 5 :(得分:0)

不幸的是,鉴于约束,你无法解决你所提到的问题。

如果弹出窗口略有不同,可以将它们实现为1个类,并使用一个属性来定义您拥有的弹出窗口类型。

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

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