我试图根据一些计算或条件逻辑将值从一个枚举映射到另一个枚举,我需要执行这些计算或条件逻辑来为类变量设置正确的枚举值。如何才能在不使用太多if/else、switch语句的情况下做到这一点?
Enum BRAND {
MINI, FERRARI, PAGANI
}
和另一个枚举
Enum ENGINE {
LEVEL1, LEVEL2, LEVEL3
}
我有一个这样的类:
Class Car() {
int model;
int year;
Engine engine;
// I want to calculate set the engine depending on the brand based on conditional logic
public carEngineCalculator (Brand b) {
Car mycar = new Car();
if (mycar.isSuperCar(b) {
if (mycar.isCrazyGood(b)) {
mycar.engine = ENGINE.LEVEL1;
} else {
mycar.engine = ENGINE.LEVEL2;
}
} else {
mycar.engine = ENGINE.LEVEL3;
}
... //And the conditions can be more complex
}
public boolean isSuperCar(Brand b) {
if (b.FERRARI || b.PAGANI) {
return true;
}
return false;
}
public boolean isCrazyGood(Brand b) {
return ...;
}
}
可能有不止一个这样的条件需要检查才能设置值,我希望避免上面显示的令人讨厌的if/else/switch语句。有没有更实用的方法来做这件事。
发布于 2018-10-19 17:20:46
如我所说,使用谓词将如下所示:
public enum Brand {
MINI,
FERRARI,
PAGANI
}
public enum Engine {
LEVEL1,
LEVEL2,
LEVEL3
}
public class Entry {
public final Predicate<Car> pred;
public final Engine engine;
public Entry(Predicate<Car> pred, Engine engine) {
this.pred = pred;
this.engine = engine;
}
}
public class Car {
int model;
int year;
Engine engine;
public void carEngineCalculator(Brand b) {
Car mycar = new Car();
List<Entry> cases = new ArrayList<>();
cases.add(new Entry(c -> c.isSuperCar(b) && c.isCrazyGood(b), Engine.LEVEL1));
cases.add(new Entry(c -> c.isSuperCar(b) && !c.isCrazyGood(b), Engine.LEVEL2));
cases.add(new Entry(c -> !c.isSuperCar(b), Engine.LEVEL3));
mycar.engine = cases.stream().filter(x -> x.pred.test(mycar)).findFirst().get().engine;
}
public boolean isSuperCar(Brand b) {
if ((b == Brand.FERRARI) || (b == Brand.PAGANI)) {
return true;
}
return false;
}
public boolean isCrazyGood(Brand b) {
return false;
}
}
您创建了一个包含谓词和结果的列表,并使用stream、filter和findFirst遍历该列表并找到正确的结果。如果条件比这更简单,那么您就不需要谓词,并对其进行稍微不同的测试。
发布于 2018-10-11 09:23:23
首先,将isSuperCar
和isCrazyGood
方法移到Brand
中,而不是让它们接受Brand
参数。类似地,您可以向Engine
添加一个静态工厂方法来封装您试图编码的逻辑。这并不能完全避免“讨厌的if/else/switch语句”,但它的可读性可能要好得多。
例如:
public Car(Brand b) {
this.engine = Engine.forBrand(b);
}
然后:
enum Engine {
LEVEL1, LEVEL2, LEVEL3
public static Engine forBrand(Brand b) {
if (b.isSuperCar()) {
return b.isCrazyGood() ? LEVEL1 : LEVEL2;
}
return LEVEL3;
}
}
还要注意,您的isSuperCar
方法可以简单地为:
return b.equals(Brand.FERRARI) || b.equals(Brand.PAGANI);
永远不需要编写if (...) return true; else return false;
或任何类似的东西-只需直接在if
语句中使用布尔表达式即可。
发布于 2018-10-17 16:10:03
如果Brand和Engine的映射是一对一的,您可以这样做:
enum Brand {
MINI(Engine.LEVEL1),
FERRARI(Engine.LEVEL2),
PAGANI(Engine.LEVEL3);
private final Engine engine;
private Brand(Engine engine) {
this.engine = engine;
}
public final Engine getEngine() {
return engine;
}
}
另一种选择:
enum Brand {
MINI(false, false),
FERRARI(true, true),
PAGANI(false, true);
private final boolean superCar;
private final boolean crazyGood;
private Brand(boolean superCar, boolean crazyGood) {
this.superCar = superCar;
this.crazyGood = crazyGood;
}
public final Engine getEngine() {
if (superCar) {
return (crazyGood) ? Engine.LEVEL1 : Engine.LEVEL2;
}
return Engine.LEVEL3;
}
}
如果映射不是一对一的,并且您需要以某种方式基于某些参数动态计算引擎,则还可以使用以下方法:
enum Brand {
MINI {
@Override
public Engine getEngine(boolean superCar, boolean crazyGood) {
return (superCar && crazyGood) ? Engine.LEVEL1 : Engine.LEVEL2;
}
},
FERRARI {
@Override
public Engine getEngine(boolean superCar, boolean crazyGood) {
return superCar ? Engine.LEVEL1 : Engine.LEVEL3;
}
},
PAGANI {
@Override
public Engine getEngine(boolean superCar, boolean crazyGood) {
return Engine.LEVEL3;
}
};
public abstract Engine getEngine(boolean superCar, boolean crazyGood);
}
或者像这样的东西,你有一些默认值,只有在特殊情况下才会覆盖:
enum Brand {
MINI,
FERRARI {
@Override
public Engine getEngine(boolean superCar, boolean crazyGood) {
return superCar ? Engine.LEVEL1 : Engine.LEVEL3;
}
},
PAGANI;
public Engine getEngine(boolean superCar, boolean crazyGood) {
return Engine.LEVEL3;
}
}
使用枚举的可能性很大,实际上我更喜欢使用枚举而不是复杂的if/else或switch语句。当然,这取决于你到底想做什么,而且由于没有提供太多信息,我真的不能给出最好的答案。希望这能对你有所帮助。
https://stackoverflow.com/questions/52731165
复制相似问题