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