如何在Java中扩展不可变类型

Med*_*o42 9 java oop immutability

在使用"公共最终字段"方法时,我开始在游戏项目中使用Java中的不可变值对象:

public class Team {
    public final String name, flag;

    public Team(String name, String flag) {
        this.name = name;
        this.flag = flag;
    }
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,这对我来说非常有效,但我需要在不同情况下提供有关团队的各种额外信息.例如,团队在比赛期间具有设定的颜色.问题是,处理这些扩展信息集的最佳方法是什么?我知道这是一个相当普遍的问题,但我想继续使用不可变对象,这可能会影响解决方案.

以下是我提出的选项.他们中的大多数可能"足够好",但我想学习一些支持和反对它们的论据以供将来参考.

选项1:一个类中的所有内容

public class Team {
    public final String name, flag, colorName;
    public final int colorRgb;

    public Team(String name, String flag, String colorName, int colorRgb) {
        this.name = name;
        this.flag = flag;
        this.colorName = colorName;
        this.colorRgb = colorRgb;
    }
}
Run Code Online (Sandbox Code Playgroud)

对于所有用途,这只需要一个类,但是没有基于类型的指示来指示预期/提供的额外数据.

选项2:子类化

public class TeamWithColor extends Team {
    public final String colorName;
    public final int colorRgb;

    public Team(String name, String flag, String colorName, int colorRgb) {
        super(name, flag);
        this.colorName = colorName;
        this.colorRgb = colorRgb;
    }
}
Run Code Online (Sandbox Code Playgroud)

这可能使基于内容的equals()实现变得不可能.

选项3:组成

public class TeamWithColor {
    public final Team team;
    public final String colorName;
    public final int colorRgb;

    public Team(Team team, String colorName, int colorRgb) {
        this.team = team;
        this.colorName = colorName;
        this.colorRgb = colorRgb;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果团队数据和额外数据经常独立更改,则减少复制/样板代码.

选项4:Pair/Tuple(使用不可变的Pair类)

public class TeamColor {
    public final String colorName;
    public final int colorRgb;

    public Team(String colorName, int colorRgb) {
        this.colorName = colorName;
        this.colorRgb = colorRgb;
    }
}

Pair<Team, TeamColor> teamWithColor = Pair.create(team, teamColor);
Run Code Online (Sandbox Code Playgroud)

...或者将Team和TeamColor联系在一起的自定义类.

我倾向于选择3或4,但我对你的意见,论点和直觉感兴趣:)

小智 6

如你所说.团队可以出现在不同的情况下.这些情况是给团队提供额外属性的背景.

因此,我建议在添加数据的每个不同上下文中使用合成.

public class TeamWithColor {
    public final Team team;
    public final TeamColor teamColor;

    public Team(Team team, TeamColor teamColor) {
        this.team = team;
        this.teamColor = teamColor;
    }
}
Run Code Online (Sandbox Code Playgroud)

也许你会:

public class TeamDuringOlimpics{
    public final Team team;
    public final TeamColor teamColor;
    public final TeamFlag teamFlag;

    public Team(Team team, TeamColor teamColor, TeamFlag teamFlagTeamFlag teamFlag) {
        this.team = team;
        this.teamColor = teamColor;
        this.teamFlag = teamFlag;
    }    
}
Run Code Online (Sandbox Code Playgroud)