Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.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 如何初始化输入字段而不写入“;如果语句“;?_Java_Design Patterns_If Statement_Enumeration - Fatal编程技术网

Java 如何初始化输入字段而不写入“;如果语句“;?

Java 如何初始化输入字段而不写入“;如果语句“;?,java,design-patterns,if-statement,enumeration,Java,Design Patterns,If Statement,Enumeration,我有一个类似的枚举 public enum Field { A, B, C, D, E ....; private Field(){ } } 我有一个类面板,它需要字段数组来初始化字段: public class Panel { TextBox A; TextBox B; TextBox C; TextBox D; TextBox E; ... public Panel(Field[]

我有一个类似的枚举

public enum Field {
     A, B, C, D, E ....;

     private Field(){
     }
}
我有一个
类面板
,它需要
字段数组
来初始化字段:

public class Panel {
     TextBox A; 
     TextBox B;
     TextBox C;
     TextBox D;
     TextBox E;
     ...


     public Panel(Field[] fields){
          this.fields = fields;
          init();
     }

     public void initA(){}
     public void initB(){}
     public void initC(){}
     public void initD(){}
     public void initE(){}
}
我的问题是,如何在不编写许多if语句的情况下初始化给定的字段

我找不到任何解决方案,现在正在进行如下初始化:

public void init(){
      for(int i = 0 ; i < fields.length; i++){
          if(fields[i] == Field.A){
              initA();
          } else if(fields[i] == Field.B){
              initB();
          } else if(fields[i] == Field.C){
              initC();
          } else if(fields[i] == Field.D){
              initD();
          } else if(fields[i] == Field.E){
              initE();
          }  ....
      }
}
public void init(){
for(int i=0;i
您可以使用java反射在枚举中循环,但您确实应该寻找某种方法来整合所有initN()方法。

从设计角度来看,我会选择工厂模式、单例模式(基于枚举)和命令模式的组合。我看到一组命令,其中每个命令都是特定于给定值的。工厂(单例)是创建此类专用实例的常见模式。即使它只是将if/开关链移动到工厂中(但允许工厂使用条件检查来创建实例…)



我认为,如果不使用命名约定和反射/实例化,或者不引入所有初始值设定项共享同一代码的约束,我们无法摆脱所有条件检查。

听起来您的设计可能需要考虑。一些建议:

  • 将init方法添加到枚举中。所以 然后你可以在数组中迭代 并调用init 方法,因此枚举知道如何 进行自己的初始化
  • 创建一个命令对象,该对象 初始化并创建一个 将枚举映射为键和 将命令作为值。周期 运行命令使地图变圆 对于每个枚举
  • 使用反射-从成本角度看,我不会对此太在意,除非您的系统经过了难以置信的低延迟
对于第一个项目符号,您可以更改文本框,使其对应一个字段类型,例如

TextBox A = new TextBox(Field.A);
TextBox B = new TextBox(Field.B);
因此,如果TextBox知道它是A、B、C、D、E,那么您只需要围绕字段[]循环,当它找到匹配的TextBox时,运行init代码(可以针对特定的enum实例存储)。当然,您需要在某个地方的数据结构中注册所有TextBox实例,因为您似乎非常反对使用非常广泛使用的反射API


本质上,字段和文本框之间必须有一个链接。Java无法读懂您的想法,并且在您不告诉它的情况下就知道这一点。好吧,至少在谷歌发布他们的心灵感应API之前是这样的(而且那可能只适用于Go…)。这可以基于命名(反射)、硬编码逻辑(ifs或开关)或状态来完成。对于后者,这意味着将字段与文本框相关联,正如我在上面的构造函数示例中所演示的那样

您可以这样做,例如,将初始化逻辑移动到枚举。有一个方法initialize,它将文本框作为参数并初始化它

顺便说一句,最好将文本框变量放在数组中

编辑 另一个选择是,我经常使用枚举作为一种原型存储。在这里,我有一个方法返回一个与某个枚举类型匹配的对象

如果不希望在枚举中进行初始化,可以将其移动到要返回的对象。对于每个特定对象,都有一个单独的初始化

恐怕你是想用这个来追龙。 这样看。由于您的问题是“有条件的”,即您必须根据字段的枚举类型进行不同的初始化,因此在某些情况下,您必须使用ifs或switch语句


相信没有神奇的方法可以绕过它,程序应该如何知道你想要做什么?即使使用反射,您也将使用ifs等相应地初始化它。

最好将init移动到枚举中,就像:

public enum Example{ 
  value1(1), 
  value2(2), 
  value3(66);

  private final int internalValue;

  Example(int value){ 
       this.internalValue = value; 
  }

  public int getInternalValue(){ 
       return this.internalValue; 
  }
}

虽然这是一个非常简单的示例,但您可以稍后向构造函数添加任何代码,并根据实际对象本身做出更复杂的决策。

为什么当前的实现不好?只是因为它看起来“丑陋”?如果出现以下情况,您可以使用switch而不是bunch of:

  public void init(){
    for(int i = 0 ; i < fields.length; i++){
        switch(fields(i)){
          case A:
            initA();
            break
          case B:
          ...
        }
    }
  }
public void init(){
for(int i=0;i

也许是initA,initB中的逻辑。。。很相似吗?如果您有20个不同的枚举,要运行20个不同的init,那么没有太多的改进空间。

正如@planetjones所提到的,您可以向enum类添加一个
init()
方法。init方法应该返回对其(enum)类型的初始化的
文本框的引用。如果您需要将数据传递给initialisor,您可以传递
,以便它可以检索所需的任何信息

要解决查找要分配给的变量的问题,可以声明
TextBox
es的数组

public void init(){
  for(int i = 0 ; i < fields.length; i++){
      F[i] = fields[i].init(this);
  }
}
public void init(){
for(int i=0;i
或者在初始化临时数组后分配它们

public void init(){
  TextBox F[5];
  for(int i = 0 ; i < fields.length; i++){
      F[i] = fields[i].init(this);
  }
  A = F[0];
  B = F[1];
  C = F[2];
  D = F[3];
  E = F[4];
}
public void init(){
文本框F[5];
for(int i=0;i

当然,您应该声明常量,而不是使用幻数。

如果与每个文本框关联的init方法非常不同,并且字段列表很小,那么您的方法一点也不差。另外,如果您通常只在
public void init(){
  for(int i = 0 ; i < fields.length; i++){
      F[i] = fields[i].init(this);
  }
}
public void init(){
  TextBox F[5];
  for(int i = 0 ; i < fields.length; i++){
      F[i] = fields[i].init(this);
  }
  A = F[0];
  B = F[1];
  C = F[2];
  D = F[3];
  E = F[4];
}
enum Field
{
  A{public void init(){initA();}},
  B{public void init(){initB();}},
  C{public void init(){initC();}},

  public abstract void init();
}
import java.util.HashMap;
import java.util.Map;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class FooPanelMain {

    public static void main(String[] args) {

        FooPanel panel = new FooPanel();
        JFrame frame = new JFrame();
        frame.getContentPane().add(panel);
        frame.pack();
        frame.setVisible(true);
    }

}    

class FooPanel extends JPanel {

    // fields are dynamically created, so we put them into a map
    private Map<PanelField, JLabel> fields = new HashMap<PanelField, JLabel>();

    // enum to configure the fields
    private enum PanelField {
        FIRST("first text"), 
        SECOND("second text"), 
        LAST("last text");

        private String text;

        private PanelField(String text) {
            this.text = text;
        }

        public String getLabelName() {
            return text;
        }

    }
        // constructor uses the enum configuration to create the fields
    public FooPanel() {
        for (PanelField fooPanelField : PanelField.values()) {
            createLabel(fooPanelField);
        }
    }

    private void createLabel(PanelField field) {

        JLabel label = new JLabel(field.getLabelName());
        this.add(label);
        fields.put(field, label);
    }
}