Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java “如果”语句与面向对象设计-2_Java_Design Patterns_If Statement - Fatal编程技术网

Java “如果”语句与面向对象设计-2

Java “如果”语句与面向对象设计-2,java,design-patterns,if-statement,Java,Design Patterns,If Statement,我遇到了类似的问题,但略有不同。在listbox的ValueChange上打开不同对象/弹出窗口的问题如下 Popup1 p1; // different objects Popup2 p2; // different objects Popup3 p3; ... listbox.add("p1"); listbox.add("p2"); listbox.add("p3"); ... listbox.addChangeHandler() { if(getSelectedItem().

我遇到了类似的问题,但略有不同。在listbox的ValueChange上打开不同对象/弹出窗口的问题如下

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=newpopup1;p1.中心

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

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

map() {

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

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

一个缺点是初始化所有弹出窗口。但只有当值发生变化时才需要,如果P1和P2都实现相同的接口,即

Popup1 implements Showable
Popup2 implements Showable
然后你可以简单地做

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

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

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

我同意在可能的情况下利用公共基类,但对于可能需要在不同子类之间进行选择的每个用法,不能总是向基类添加方法

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

一个缺点是初始化所有弹出窗口。但只有当价值发生变化时才需要

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

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

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

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

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

不幸的是,考虑到这些限制因素,你提到的问题无法解决

如果弹出窗口只是略有不同,则可以将其实现为一个类,该类具有定义弹出窗口类型的属性

否则,最好将其封装在一个工厂类中,如前面提到的@JST,这样丑陋的逻辑只存在于一个地方。我不知道为什么你认为你的地图解决方案昂贵。
如果要根据名称动态调用构造函数,则必须使用动态语言而不是Java。

我这样做了,但问题出在这里。Showable Showable在此为空。然后是oops nulpointerexception。您无法初始化它,因为它们是不同的类constructor@hilal-为什么不能检查null,而不尝试对其调用方法?嗯。好的,您可以定义一个哈希表,其中必须存储每个ID和一个委托方法。然后取ID“p1”,确定委托并调用此委托。p1、p2、p3真的是不同类的三个对象,还是同一类的三个对象?如果它们属于不同的类,那么我希望它们至少是同一基类的子类。@JST是的,它们是不同的类,并且扩展同一个类谢谢你的评论,但是如果我对此过敏,你也可以写。弹出窗口计数未知。现在对我来说是9点了,我不知道你为什么这么反对if。但是您可以很容易地在工厂类中使用映射,而不是条件。但是,您不希望映射到实例化的对象,而是映射到类本身。例如,您可以将p1映射到Popup1.class。然后createPopup的主体变成:return Popup map.getpopupIdentifier.newInstance;是的,我也这样做了,但是每次初始化弹出窗口时都有很多东西。这就是为什么,我不知道。他们来自start@hilal-要清楚,此代码不会从一开始就初始化它们。使用此代码,除非在onValueChange方法期间从映射返回特定的弹出窗口,否则弹出窗口不会初始化。这将推迟弹出窗口的构造/初始化,并仅构造/初始化选定的弹出窗口。请注意,接口无法实例化,因此new Showable无效。@JST-这是一个匿名类,您可以实例化它。例如,请参阅Java中关于匿名类的一章,在示例3.11中,枚举接口是如何实例化的。另请参见和Init。调用该类时,10+弹出面板包含许多10x10+小部件。不是很贵吗?什么的成本?记忆,速度?完全可以忽略不计。试试看,看看你是否能测量出任何差异。我的猜测是:没有。