我想知道在考虑单一责任原则(SRP)的同时,有人会如何证明创建GameManager。具体例子:记忆游戏的GameManager(你必须匹配的牌)。它显然有很多责任:跟踪轮到谁,在转弯之间切换,跟踪比赛结束时,获胜者是谁以及更多......
答案 0 :(得分:3)
如果对超出对象责任有疑问。有一个与SRP相关的概念cohesion,这是非常客观的。在Konamiman's answer中,GameManager具有100%的凝聚力。这意味着所有依赖项(实例字段)都在所有公共方法中使用。
0%将是相反的:
class GameManager {
private int anInt;
private object aObj;
public void Foo() {
// Do anything but using anInt or aObj
}
}
如果在对象中发现了几个内聚组件:
class GameManager {
private T1 obj1;
private T2 obj2;
public void Foo() {
T1.F1();
}
public void Goo() {
T2.G1();
}
}
该课程应分为两部分:
class GameManagerFoo {
private T1 obj1;
public void Foo() {
T1.F1();
}
}
class GameManagerGoo {
public void Goo() {
T2.G1();
}
}
好点@Lackl56:关于财产制定者和吸气者你有2个选择。您无法将它们考虑在内,或者您可以认为它们降低了您的凝聚力,但达到了可接受的水平。
答案 1 :(得分:2)
关键是如果你做得恰当,GameManager课程不会直接承担你提到的所有责任。相反,它会将这些职责委托给其他类,这些类将通过使用某种形式的依赖注入传递给它。所以你可以说GameManager类只有一个责任:协调其他类的工作;并且有一个改变的理由:适应游戏逻辑的变化,这需要新的类参与或改变类之间交互的顺序。
一个非常简单的例子(抱歉,C#语法,但你明白了):
public class GameManager
{
//constructor - note that the parameter types are interfaces, not classes
public GameManager(
IPlayerManager playerManager,
ITurnManager turnManager)
{
this.playerManager = playerManager;
this.turnManager = turnManager;
}
public void DoNextTurn()
{
var nextPlayer = playerManager.GetNextPlayer();
turnManager.ProcessTurn(nextPlayer);
//etc...
}
}