得墨忒耳法则——只用一个点,我能改进这个逻辑吗?

Law of demeter - using only one dot, could I improve this logic?

我有以下方法:

    private boolean reserveSeat(int selectedRow, int selectedSeat) {
    if (show.getRows().get(selectedRow).getSeats().get(selectedSeat).getReservationStatus()) {
        return false;
    } else {
        show.getRows().get(selectedRow).getSeats().get(selectedSeat).reserve();
        setRowNumber(selectedRow);
        setSeatNumber(selectedSeat);

        return true;
    }
}

位于预订 class 中。这个class有一个Show Object(表演),A show有Rows(另一个对象),Rows有Seats(另一个对象)。

我的问题是这个方法可以改进吗?我读过关于 LoD 的文章,虽然我认为这是合乎逻辑的,但我担心我的点表示设计不好。它是 Seat 对象,知道它是否被保留。但是从 Show 到 Seat 会和陌生人说话吗?还是因为每个对象包含下一个对象的方式没问题?

如果我的问题不清楚,请见谅。我似乎发生了什么(可能是因为我是自学的)是我设计了一些可行的东西,然后我阅读了一些 OOP 设计原则并认为废话,它可行但不是好的设计!

任何建议表示赞赏。

是的,调用链太长了。 如果show负责座位, 那么如果它完全负责会更好。 现在它还没有完全负责, 因为可以在演出不知情的情况下预订座位。 这种职责分散很奇怪。

您可以通过不将 Seat 暴露给 Reservation,让 show 完全负责, 通过隐藏辅助方法背后的座位状态操作:

private boolean reserveSeat(int selectedRow, int selectedSeat) {
    if (show.isSeatReserved(selectedRow, selectedSeat)) {
        return false;
    } else {
        show.reserveSeat(selectedRow, selectedSeat);
        setRowNumber(selectedRow);
        setSeatNumber(selectedSeat);

        return true;
    }
}

或者,如果您不希望 show 负责座位, 那么它根本不应该知道座位, 那么您将无法通过 show 获得座位, 但另一个 class 负责这件事。

您正在使用 show 作为数据对象,并将处理该数据的所有逻辑放在包含它的 class 中。这使得 Show 成为数据 class 并且封闭的 class 成为神 class.

inside show 的处理数据的逻辑实际上应该在 Show class 本身内部(数据是智能的)。

您可以在 Show class 中创建一个方法来预订座位。同样,您可以在 Row class 中创建一个方法来预订座位。

然后一个人将消息传递给下一个,直到你到达 Seat


如果您将 Show 的实现更改为例如使用二维数组会怎样?这会破坏您预订中的密码 class.

通过执行这些长链调用,而不让 classes 处理自己的数据。您正在使用户 classes 依赖于所用数据结构的实现。

如果您想更改一个,则必须更新所有用户 class,而不仅仅是包含数据结构的 class。

非常感谢您的建议,反馈对我的学习非常有帮助。所以我接下来要做的是,基于关系--> A Reservation (now called Booking) has a Show, A Show 有一个 Row, A 有一个 座位(s)。

在预订中 class 我现在有这个:谢谢@janos

private boolean reserveSeat(int selectedRow, int selectedSeat) {
    if (show.isSeatReserved(selectedRow, selectedSeat)) {
        System.out.println("Sorry, that seat has already been booked");
        return false;
    } else {
        show.reserveSeat(selectedRow, selectedSeat);
        setRowNumber(selectedRow);
        setSeatNumber(selectedSeat);
        System.out.println("This seat has now been booked.");
        return true;
    }
}

在节目中 class 我有这个:

public boolean isSeatReserved(int selectedRow, int selectedSeat) {
    if (getRow(selectedRow).getSeatStatus(selectedSeat)) {
        return true;
    } else
        return false;
}

行class我有

public boolean getSeatStatus(int selectedSeat) {
    return getSeat(selectedSeat).getReservationStatus();
}

我认为使用从 jarchitect 工具中获取的之前和之后的图表以图形方式显示这一点可能对其他刚起步的人(例如我)有用,这些图表显示了我的代码有多混乱!我用同样的逻辑整理了一些 class 的 "knew too much".