我有这种随机选择程序执行的程序结构。然而,这种风格不可扩展、不可维护,而且非常容易出错。正如您所看到的,if语句的条件变得越来越长且不可读
你能建议一个更好的编程风格/结构吗?
double aProb = 0.4;
double bProb = 0.2;
double cProb = 0.2;
double dProb = 0.2;
double chance = random.nextDouble();
if ( chance < aProb ) {
a();
}
if ( chance < bProb + aProb ) {
b();
}
if ( chance < cProb + bProb + aProb ) {
c();
}
if ( chance < dProb + cProb + bProb + aProb ) {
d();
}
我想这很清楚。
如果你想要更短,
double chance = random.nextDouble();
if ((chance -= 0.4) < 0) {
a();
} else if ((chance -= 0.2) < 0) {
b();
} else if ((chance -= 0.2) < 0) {
c();
} else {
d();
}
(我假设你想要else if
)
您可以创建一个新变量来存储aProb + bProb
,就像在每个if
语句中使用的那样,除了第一个语句,这会使它更短。
您可以创建abstract class IntervalAction
类:
public abstract class IntervalAction {
private final double minBound;
private final double maxBound;
public IntervalAction(double minBound, double maxBound) {
if (minBound < 0) throw new IllegalArgumentException("minBound >= 0");
if (maxBound > 1) throw new IllegalArgumentException("maxBound <= 0");
if (minBound > maxBound) throw new IllegalArgumentException("maxBound >= minBound");
this.minBound = minBound;
this.maxBound = maxBound;
}
public abstract void execute();
@Override
public String toString() {
return "IntervalAction{" +
"minBound=" + minBound +
", maxBound=" + maxBound +
'}';
}
}
和注册表类,它将包含所有可用的操作:
public class ActionRegistry {
public void register(IntervalAction action) {
if (intersectsWithExistingRange(action))
throw new IllegalArgumentException("Already have action in that range: " + action);
// todo registration in internal data structure
}
private boolean intersectsWithExistingRange(IntervalAction action) {
// todo
return true;
}
public void execute(double input) {
IntervalAction action = find(input);
if (action == null) throw new IllegalArgumentException("No action found for " + input);
action.execute();
}
private IntervalAction find(double input) {
// todo
return null;
}
}
和一个驱动类:
public class ActionDriver {
private final ActionRegistry registry;
private final Random random;
public ActionDriver() {
random = new Random(System.currentTimeMillis());
registry = new ActionRegistry();
registry.register(new IntervalAction(0, 0.1) {
@Override
public void execute() {
System.out.println(this);
}
});
registry.register(new IntervalAction(0.1, 0.2) {
@Override
public void execute() {
System.out.println(this);
}
});
// so on
}
public void act() {
registry.execute(random.nextDouble());
}
}
现在,最有趣的部分是如何在ActionRegistry
中实现内部数据结构来保存(和搜索)您的操作——所有这些todos
在上面的代码示例中。为此,我建议你参考这个SO问题。