gpt4 book ai didi

java - 如何重构嵌套的切换用例(Java)或何时重构(Kotlin)?

转载 作者:行者123 更新时间:2023-12-02 13:30:52 27 4
gpt4 key购买 nike

要求:我需要编写一个可以与多个玩家一起玩的Jo-Ken-Pô游戏代码。有5个角色(SPOCK,剪刀,纸张,石头和蜥蜴)。我可以用这两个链接的when / switch来完成它(波纹管代码使用when(),因为它在Kotlin中,但是可以使用Java中的switch来应用相同的想法)

  when (u1.play) {
PlayType.SPOCK -> when (u2.play) {
//SPOCK WINS
PlayType.TESOURA -> return u1
PlayType.PEDRA -> return u1
//SPOCK LOSES
PlayType.PAPEL -> return u2
PlayType.LAGARTO -> return u2
}
PlayType.TESOURA -> when (u2.play) {
//TESOURA (scissors) WINS
PlayType.PAPEL -> return u1
PlayType.LAGARTO -> return u1
//TESOURA (scissors) LOSES
PlayType.SPOCK -> return u2
PlayType.PEDRA -> return u2
}
PlayType.PAPEL -> when (u2.play) {
//PAPEL (paper) WINS
PlayType.SPOCK -> return u1
PlayType.PEDRA -> return u1
//PAPEL (paper) LOSES
PlayType.TESOURA -> return u2
PlayType.LAGARTO -> return u2
}
PlayType.PEDRA -> when (u2.play) {
//PEDRA (stone) WINS
PlayType.LAGARTO -> return u1
PlayType.TESOURA -> return u1
//PEDRA (stone) LOSES
PlayType.SPOCK -> return u2
PlayType.PAPEL -> return u2
}
PlayType.LAGARTO -> when (u2.play) {
//LAGARTO (lizard) WINS
PlayType.SPOCK -> return u1
PlayType.PAPEL -> return u1
//LAGARTO (lizard) LOSES
PlayType.TESOURA -> return u2
PlayType.PEDRA -> return u2
}
}

我已经阅读了数小时的尝试,试图找到如何使用lambda将代码变得更优雅,但我找不到任何线索。请帮助您。

我将在此处粘贴整个代码。尽管您看到我至少使用lambda来调用该方法,但我肯定缺少lambda的一些强大功能,并且几乎像Java 7 <经典方式那样进行编码。

所有用户都来自H2数据库。这是仓库
import com.mycomp.jokenpo.model.User
import org.springframework.data.repository.CrudRepository

interface UserRepository : CrudRepository<User, Long>

用户模型
import com.mycomp.jokenpo.enums.PlayType
import javax.persistence.*


@Entity
data class User(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long,

@Column(nullable = false)
val name: String,

@Enumerated
@Column(nullable = false)
val play: PlayType

)

枚举播放类型
enum class PlayType(val value: Int) {
SPOCK(1), TESOURA(2), LAGARTO(3), PAPEL(4), PEDRA(5)
}

服务 *这里是问题*
import com.mycomp.jokenpo.enums.PlayType
import com.mycomp.jokenpo.model.User
import com.mycomp.jokenpo.respository.UserRepository
import org.springframework.stereotype.Component

@Component
class GameService(private val userRepository: UserRepository) {

fun returnWinnerBetweenTwoPlayers(u1: User, u2: User): User {

when (u1.play) {
PlayType.SPOCK -> when (u2.play) {
//SPOCK WINS
PlayType.TESOURA -> return u1
PlayType.PEDRA -> return u1
//SPOCK LOSES
PlayType.PAPEL -> return u2
PlayType.LAGARTO -> return u2
}
PlayType.TESOURA -> when (u2.play) {
//TESOURA (scissors) WINS
PlayType.PAPEL -> return u1
PlayType.LAGARTO -> return u1
//TESOURA (scissors) LOSES
PlayType.SPOCK -> return u2
PlayType.PEDRA -> return u2
}
PlayType.PAPEL -> when (u2.play) {
//PAPEL (paper) WINS
PlayType.SPOCK -> return u1
PlayType.PEDRA -> return u1
//PAPEL (paper) LOSES
PlayType.TESOURA -> return u2
PlayType.LAGARTO -> return u2
}
PlayType.PEDRA -> when (u2.play) {
//PEDRA (stone) WINS
PlayType.LAGARTO -> return u1
PlayType.TESOURA -> return u1
//PEDRA (stone) LOSES
PlayType.SPOCK -> return u2
PlayType.PAPEL -> return u2
}
PlayType.LAGARTO -> when (u2.play) {
//LAGARTO (lizard) WINS
PlayType.SPOCK -> return u1
PlayType.PAPEL -> return u1
//LAGARTO (lizard) LOSES
PlayType.TESOURA -> return u2
PlayType.PEDRA -> return u2
}
}
return u1
}

fun playGameWithAll(): User? {
val allUsers = userRepository.findAll().toList()

val winner = allUsers.reduce { a, b ->
returnWinnerBetweenTwoPlayers(a, b)
}

if (allUsers.filter { player -> player.play == winner.play }
.count() == 1)
return winner
else
return null

}
}

上面的代码按预期工作,但是由于两个原因,我的代码很糟糕:

1-我拆分了两个小的lambda语句:减少以比较彼此的播放类型,并判断是否有多个我编码的获胜者。

2-当然,用lambda编码两个链接的开关可能会有更优雅,更易读的方式,但是我什至可以尝试的第一步

PS:代码是Kotlin,但是如果您用Java指向任何东西,我都可以轻松地将其翻译为kotlin。任何技巧或建议将如何使工厂受到高度赞赏

任何有兴趣获得免费游戏的人都可以从 https://github.com/jimisdrpc/games.git复制

***在米哈伊尔的回答后编辑

Main.java
    package poc;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

public class Main {

public static void main(String[] args) {

//Fake returned list from database
List<User> usersList = List.of(
new User(1L, "Jimis", PlayType.LAGARTO),
new User(2L, "Drpc", PlayType.PAPEL));


//User winnerUser = returnWinnerBetweenTwoPlayers(usersList.get(0), usersList.get(1));

Optional<User> winnerUser = usersList.stream().reduce( (a, b) ->
returnWinnerBetweenTwoPlayers(a , b));

System.out.print(winnerUser);

}

//Trying to refactoring from classical switch to some structure for using with lambda
private final static Map<PlayType, Set<PlayType>> CONFIG = Map.of(
PlayType.SPOCK,
Set.of(PlayType.TESOURA, PlayType.PEDRA),
PlayType.TESOURA,
Set.of(PlayType.PAPEL, PlayType.LAGARTO)

);

private static User returnWinnerBetweenTwoPlayers(User u1, User u2) {
/// ****** Exception next line
if (CONFIG.get(u1.getPlay()).contains(u2.getPlay())) {
return u1;
}
return u2;
}
}

用户模型
package poc;

public class User {

Long id;
String name;
PlayType play;

public User(Long id, String name, PlayType play) {
super();
this.id = id;
this.name = name;
this.play = play;
}

//... getters/setters removed
}

PlayType枚举
package poc;

public enum PlayType {
SPOCK,
TESOURA,
PEDRA,
PAPEL,
LAGARTO;
}

运行此部分时发生异常CONFIG.get(u1.getPlay())。contains(u2.getPlay()
Exception in thread "main" java.lang.NullPointerException
at moduleinfo/poc.Main.returnWinnerBetweenTwoPlayers(Main.java:39)
at moduleinfo/poc.Main.lambda$0(Main.java:21)
at java.base/java.util.stream.ReduceOps$2ReducingSink.accept(ReduceOps.java:123)
at java.base/java.util.AbstractList$RandomAccessSpliterator.forEachRemaining(AbstractList.java:720)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.reduce(ReferencePipeline.java:558)
at moduleinfo/poc.Main.main(Main.java:20)

如果我尝试简化并在不使用stream()。reduce()的情况下调用,则会在同一点出现此问题
Exception in thread "main" java.lang.NullPointerException
at moduleinfo/poc.Main.returnWinnerBetweenTwoPlayers(Main.java:49)
at moduleinfo/poc.Main.main(Main.java:19)

***最终解决方案
public class Main {

public static void main(String[] args) {

//Fake returned list from database
List<User> usersList = List.of(
new User(1L, "Jogador 1", PlayType.PEDRA),
new User(2L, "Jogador 2", PlayType.TESOURA),
new User(3L, "Jogador 3", PlayType.TESOURA),
new User(4L, "Jogador 4", PlayType.SPOCK)
);


Optional<User> winnerUser = usersList.stream().reduce( (a, b) ->
returnWinnerBetweenTwoPlayers(a , b));

System.out.print(winnerUser.get().getName());

}

private final static Map<PlayType, Set<PlayType>> CONFIG = Map.of(
PlayType.SPOCK,
Set.of(PlayType.TESOURA, PlayType.PEDRA),
PlayType.TESOURA,
Set.of(PlayType.PAPEL, PlayType.LAGARTO),
PlayType.PAPEL,
Set.of(PlayType.SPOCK, PlayType.PEDRA),
PlayType.PEDRA,
Set.of(PlayType.LAGARTO, PlayType.TESOURA),
PlayType.LAGARTO,
Set.of(PlayType.SPOCK, PlayType.PAPEL)
);

private static User returnWinnerBetweenTwoPlayers(User u1, User u2) {
if (CONFIG.get(u1.getPlay()).contains(u2.getPlay())) {
return u1;
}
return u2;
}
}

最佳答案

正确,这种switch inside switch构造看起来很难阅读。

这样想:每个PlayType都从另一个中获胜。而且此信息看起来像配置,因此可以以声明的方式进行描述,如下所示:

  • SPOCK击败TESOURA和PEDRA
  • TESOURA击败PAPEL和LAGARTO赢得

  • 因此,您只需定义一个 Map<PlayType, Set<PlayType>>并验证 u2.play is contained by map.get(u1.play)是否

    UPD。代码示例(java,用记事本编写,因此可能包含一些语法错误)

    class GameService {
    private final static Map<PlayType, Set<PlayType>> CONFIG = Map.of(
    PlayType.SPOCK, Set.of(PlayType.TESOURA, PlayType.PEDRA),
    PlayType.TESOURA, Set.of(PlayType.PAPEL, PlayType.LAGARTO)
    //etc
    );

    function User returnWinnerBetweenTwoPlayers(User u1, User u2){
    if (CONFIG.get(u1.getType()).contains(u2.getType()){
    return u1;
    }
    return u2;
    }
    }

    关于java - 如何重构嵌套的切换用例(Java)或何时重构(Kotlin)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61451518/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com