我的问题与面向对象编程中的“组合”方面有关。我正在用Java编程,但这可能适用于任何语言。

我的问题是2向合成。我听说构图暗示着“有”的关系。假设您正在构建一个跳棋游戏,就我而言,我将拥有一个用于生成棋盘的“棋盘”类,一个棋盘具有正方形,并且正方形可以拥有棋子(棋子类)或为空。组成(根据我的理解)会说我们的木板中应该有一个正方形的对象阵列,而正方形中的一个对象应该是一块区域。

public class Board {

    private List<Square>;

    ... (generating board, other functions/fields)

}




public class Square {

    private Piece piece;

    ... (other functions/fields)

}




public class Piece {

    ... (functions/fields)

}


这就是我对构图的理解。我的问题是,是的,一块木板有正方形和一块,但是一块也有一块木板,这不是很有意义吗?如果您在piece类中创建了move方法,您是否不需要访问木板及其正方形?像这样:

public class Piece {

    private Board board;

    ... (constructor/functions/fields)

    public void move(int x, int y) {

        if (this.board.getSquare(x, y).isEmpty())
            System.out.println("Piece moves to (x, y)");

        ... (etc.)
    }
}


这被认为是好的设计实践,还是会有更好的方法来实现呢?

最佳答案

确实有两个问题。双向组合-或通常来说是双向关联-本身不是问题。这是一种绝对有效的关系类型,尽管在实现中有些不切实际。双向关联增加了一个依赖关系,每增加一个依赖关系都会增加耦合(请检查Craig Larman作为其GRASP原理的一部分解释的低耦合)。

尽管如此,有时还是需要双向关联来反映两个对象仅在一起才有意义的事实。是的,您可以说一块有一块木板,但是在现实生活中我们真的这么说吗?我们在乎吗?从域的角度来看,这并没有扮演任何关键的角色,至少在域只是在扮演支票的时候。也许在另一个虚构的领域中,即我们在许多板之间移动零件时,这种观点可能至关重要,因此我们可能需要使用双向关联对其进行建模。现在,已经提到了域,我不得不提起Eric Evans关于域驱动设计的经典book。的确,Eric很好地解释了使用软件建模领域的所有细微差别。特别是,他还解释了对象之间的双向关联(第83页)。

现在,到第二期。在您的情况下,有必要保留对董事会的参考,以保持双向联系,这是由于分配职责将棋子移到错误的对象上引起的。移动零件是一项可能影响多个零件的操作,因此,一个特定的零件在不破坏封装的情况下将无法处理。相反,我们应该问,可以负责监督所有事务并根据域规则(打支票规则)以适当方式对其进行管理的负责任的对象是谁?在没有添加任何特殊对象的情况下,似乎已经成为董事会。电路板看起来很不错,可以容纳操纵电路板内容的逻辑(因此我们尊重封装)。

因此,回答您的实际问题时,最好将move()方法放置到Board类中,并自动摆脱不必要的双向关联。作为我提到的关于职责分配的后续措施,我将再次提及GRASP(它实际上代表一般责任分配原则)-对其进行检查,我相信这对这种情况和类似情况都会有很大帮助。

08-03 23:46