如何解决根据枚举值执行代码的最佳方式 已编辑:原文错误:
以下代码是我的问题的示例。 我想简化代码,而不必在不同的 switch 语句上重复调用相同的方法。
public void simulate(String given,Status status) {
switch (status){
case A:
simulateA(given);
break;
case B:
simulateA(given);
simulateB(given);
break;
case C:
simulateA(given);
simulateB(given);
simulateC(given);
break;
}
PS 2:我不是在寻找进行切换的另一种方式,而是在寻找对问题进行建模的另一种方式,也许在方法中使用某种类组合。
解决方法
假设您的第一个 status
是 A,您可以执行以下操作:
public void simulate(String given,Status status) {
if (status != Status.A) {
int indexOfStatus = status.ordinal();
simulate(given,Status.values()[indexOfStatus - 1]);
}
switch (status){
case A:
simulateA(given);
break;
case B:
simulateB(given);
break;
case C:
simulateC(given);
break;
// here you still need to put all your "simulateX" calls but without repetitions
}
}
,
我不知道您的 enum
的性质,但是如果您有很多模拟调用,您可以放弃 switch 语句并这样做。但是您目前的方法没有任何问题。如果您的方法是静态的而不是实例,这也会略有变化。这样做的一个优点是它具有扩展的潜力。
还有很多其他方法可以做到这一点。您可以有一个方法引用列表,enum
参数可以是通过索引调用哪些方法的变量数组。
public class Simulations {
static List<BiConsumer<Simulations,String>> sims =
List.of(Simulations::simulateA,Simulations::simulateB,Simulations::simulateC);
enum Status {
A(1),B(2),C(3);
private int val;
private Status(int v) {
this.val = v;
}
public int getVal() {
return val;
}
}
public static void main(String[] args) {
Simulations simulation = new Simulations();
simulation.simulate("A",Status.A);
System.out.println();
simulation.simulate("B",Status.B);
System.out.println();
simulation.simulate("C",Status.C);
}
public void simulate(String given,Status status) {
for (int i = 0; i < status.getVal(); i++) {
sims.get(i).accept(this,given);
}
}
public void simulateA(String s) {
System.out.println(s);
}
public void simulateB(String s) {
System.out.println(s);
}
public void simulateC(String s) {
System.out.println(s);
}
}
,
在这种情况下,模拟的顺序总是“向下”级联,例如模拟 B 就是模拟 A 加上一些额外的。这匹配继承模式,例如哺乳动物是一种带有一些额外功能的动物。因此,让模拟相互继承可以修复模式:
.git/
请注意,这很脆弱,因为所有继承树都是如此。另一种解决方案可以通过组合和委托来实现。这称为链:
interface Simulation
{
void simulate( final String given );
}
class ASimulation implements Simulation
{
@Override
public void simulate( String given )
{
// simulate this given!
}
}
class BSimulation extends ASimulation
{
@Override
public void simulate( String given )
{
super.simulate( given );
// simulate this given some more!
}
}
class CSimulation extends BSimulation
{
@Override
public void simulate( String given )
{
super.simulate( given );
// simulate this given even more!
}
}
要实例化链,请使用以下顺序:
class LeafSimulation
implements Simulation
{
@Override
public void simulate( String given )
{
// simulate this given!
}
}
class ChainedSimulation
implements Simulation
{
private final Simulation delegate;
ChainedSimulation( final Simulation delegate )
{
this.delegate = delegate;
}
@Override
public void simulate( String given )
{
delegate.simulate( given );
// simulate this given some more!
}
}
这段代码更自然地接近问题陈述并消除了重复,但并不简洁。
,设置状态值到方法调用的映射后,您可以使用 SortedSet 或 EnumSet.range 获取特定值后的枚举值:
Map<Status,Consumer<String>> simulators = new EnumMap<>(Map.of(
Status.A,this::simulateA,Status.B,this::simulateB,Status.C,this::simulateC));
if (!simulators.keySet().equals(EnumSet.allOf(Status.class))) {
throw new RuntimeException(
"Not all Status values have simulators defined.");
}
// ...
SortedSet<Status> all = new TreeSet<>(EnumSet.allOf(Status.class));
Collection<Status> remainingValues = all.tailSet(status);
// Or:
//Status[] allStatuses = Status.values();
//Status lastStatus = allStatuses[allStatuses.length - 1];
//Collection<Status> remainingValues = EnumSet.range(status,lastStatus);
for (Status s : remainingValues) {
simulators.get(s).accept(given);
}
,
要考虑的另一个选项,它避免了 switch
/ if
。声明每个 Status
值的操作映射,可与未处理值的 getOrDefault
查找默认值一起使用:
Consumer<String> simA = this::simulateA;
Map<Status,Consumer<String>> actions = new EnumMap<>(Map.of(
Status.A,simA,simA.andThen(this::simulateB),simA.andThen(this::simulateB).andThen(this::simulateC)
));
actions.getOrDefault(status,s -> {}).accept(given);
如果您想防止丢失/未处理的映射,您应该验证映射(如@VGR 答案)或用异常处理程序交换无操作默认值:
actions.getOrDefault(status,s -> { throw new RuntimeException("Missing action for status: "+status); }
).accept(given);
,
你可以试试switch语句的fallthrough机制。参考this
在您的示例中,代码可以(未测试):
已编辑:
public void simulate(String given,Status status) {
switch (status){
case C:
simulateC(given);
case B:
simulateB(given);
case A:
simulateA(given);
}
}
原文(错误):
public void simulate(String given,Status status) {
switch (status){
case A:
simulateA(given);
case B:
simulateB(given);
case C:
simulateC(given);
}
}
当读者考虑到fallthrough概念时,上面的代码比相关代码更清晰、更容易阅读。但情况并非总是如此。我的建议是重构您的代码,以消除重复调用和失败。
,你不需要为你的所有案例写simulateA(given),只需将它移到顶部
public void simulate(String given,Status status) {
simulateA(given);
switch (status){
case C:
simulateC(given);
case B:
simulateB(given);
break;
case A:
break;
}}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。