Getters和setters是糟糕的设计吗?看到相互矛盾的建议

2022-08-31 05:46:12

我目前正在用Java开发一个简单的游戏,有几种不同的模式。我扩展了一个主要游戏类,将主要逻辑放在其他类中。尽管如此,主游戏类仍然相当沉重。

在快速浏览了我的代码之后,其中大部分是Getters和Setters(60%),而其余的则是游戏逻辑真正需要的。

一些谷歌搜索声称Getters和Setters是邪恶的,而其他人则声称它们是良好的OO实践和优秀程序所必需的。

那我该怎么办呢?它应该是哪个?我应该为我的私有变量更改 Getter 和 Setters,还是应该坚持使用它们?


答案 1

还有一种观点认为,大多数时候,使用 setter 仍然会通过允许您设置无意义的值来破坏封装。举一个非常明显的例子,如果你在游戏上有一个分数计数器,它只会上升,而不是

// Game
private int score;
public void setScore(int score) { this.score = score; }
public int getScore() { return score; }
// Usage
game.setScore(game.getScore() + ENEMY_DESTROYED_SCORE);

它应该是

// Game
private int score;
public int getScore() { return score; }
public void addScore(int delta) { score += delta; }
// Usage
game.addScore(ENEMY_DESTROYED_SCORE);

这也许是一个简单的例子。我想说的是,讨论 getter/setters 与公共领域往往会掩盖更大的问题,因为对象以亲密的方式操纵彼此的内部状态,因此过于紧密地耦合在一起。

这个想法是制造直接做你想做的事情的方法。一个例子是如何设置敌人的“活着”状态。你可能会想有一个 setAlive(布尔 alive)方法。相反,您应该拥有:

private boolean alive = true;
public boolean isAlive() { return alive; }
public void kill() { alive = false; }

这样做的原因是,如果您更改实现,使事物不再具有“活动”布尔值,而是具有“命中点”值,则可以在不破坏之前编写的两个方法的契约的情况下进行更改:

private int hp; // Set in constructor.
public boolean isAlive() { return hp > 0; } // Same method signature.
public void kill() { hp = 0; } // Same method signature.
public void damage(int damage) { hp -= damage; }

答案 2
  • 非常邪恶:公共领域。
  • 有点邪恶:不需要的Getters和setters。
  • 好:Getters 和 setter 只在真正需要的地方 - 使类型公开碰巧使用其状态的“更大”行为,而不仅仅是将类型视为要由其他类型操作的状态存储库。

这实际上取决于情况 - 有时你真的只是想要一个愚蠢的数据对象。