Java 基于类中的字段选择方法
所以我有一个包含字符串字段的类:Java 基于类中的字段选择方法,java,field,visitor-pattern,Java,Field,Visitor Pattern,所以我有一个包含字符串字段的类: public class A { private String type = ... public String getType(){ return this.type; } public void setType(String type){ this.type = type; } } 我还列出了所有可能的类型,有十二种,将来可能还会更多 现在我想编写一个方法,该方法获取类a的对象,并根据
public class A {
private String type = ...
public String getType(){
return this.type;
}
public void setType(String type){
this.type = type;
}
}
我还列出了所有可能的类型,有十二种,将来可能还会更多
现在我想编写一个方法,该方法获取类a的对象,并根据类中的“类型”调用特定的方法。
有没有比写12条(或更多)if语句更聪明的解决方案?通常我会使用访问者模式,但我不想创建12个新类 编辑:
我最终创造了一个
Map<String,Function<A,String>> map = new HashMap<String,Function<A,String>>
如果您使用的是JDK 7或更高版本,请选择一个
开关
,该开关接受字符串作为参数,并为每个字符串编写大小写
switch (type) {
case "SomeX":
yourInstance.invokeMethod();
break;
case "SomeY":
...
您应该使用
enum
,而不是将类型存储为“自由格式”文本值,因为您有一个定义良好的值列表
通过使用抽象方法,您甚至可以让不同的枚举以不同的方式实现相同的方法。这将允许您完全消除容易出错的switch
语句
下面是一个显示实例值和抽象方法的示例。显示的模式将使实现不在枚举中,同时使编译器在添加新枚举时捕获所有使用
public enum Type {
INTEGER("Integer") {
@Override
public void apply(Action action, A a) {
action.applyInteger(a);
}
},
STRING ("Text") {
@Override
public void apply(Action action, A a) {
action.applyString(a);
}
};
private String displayName;
private Type(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return this.displayName;
}
public abstract void apply(Action action, A a);
}
public interface Action {
public void applyInteger(A a);
public void applyString(A a);
}
public class A {
private Type type;
public Type getType(){
return this.type;
}
public void setType(Type type){
this.type = type;
}
public void apply(Action action) {
this.type.apply(action, this);
}
}
将新类型添加到类型枚举时,还将向操作接口添加新方法,这将迫使您在接口的所有实现中实现该方法。使用
switch
语句,您不会得到这样的安全性。我想其他答案是正确的,但通过阅读问题,我认为更直接的答案将是使用内省和惯例:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
public static class A {
private String type;
public String getType(){
return this.type;
}
public void setType(String type){
this.type = type;
}
}
public static class Actions {
public void runForType1(A a) {
System.out.println("It's type 1");
}
public void runForType2(A a) {
System.out.println("It's type 2");
}
public void runForType3(A a) {
System.out.println("It's type 3");
}
}
public static class Runner {
Actions actions;
public Runner(Actions a) {
this.actions = a;
}
public void run(A a) {
try {
Method m = actions.getClass().getMethod("runFor" + a.getType(), A.class);
m.invoke(actions, a);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Runner r = new Runner(new Actions());
A type1 = new A();
type1.setType("Type1");
A type2 = new A();
type2.setType("Type2");
A type3 = new A();
type3.setType("Type3");
r.run(type1);
r.run(type2);
r.run(type3);
}
}
示例的预期输出为:
It's type 1
It's type 2
It's type 3
如果无法使用约定,则始终可以创建具有类型到方法名称映射的哈希映射。这些方法的作用是什么?为什么不把它们放在每种类型的班级里呢?听起来你愿意用代码质量换取几行节省下来的代码。你最终得到的解决方案比给出的答案要好(IMHO)。然而,Andreas关于enum优于string的建议可能值得注意。
It's type 1
It's type 2
It's type 3