使用组合访问对象方法?

Accessing object methods with composition?

这可能是一件非常简单的事情,但我似乎无法独自解决这个问题。使用组合时,访问 "inner object?" 方法的最佳方式是什么?我能想到的每一种方式似乎都违反了某些 OO 原则或其他原则。

这是一个非常宽泛的话题,但我会举一个例子来尽可能清楚地说明问题。代码是用 java 编写的,但我相信这个问题几乎适用于任何使用 OOP 的语言。

Class Shelf {
    private Book book;
}

Class Book {
    public void turnPage() {
        //do stuff
    }
}

当您只能访问 Shelf 对象时,访问 Book 方法的最佳方式是什么?我读过的一些地方建议在 Shelf 中使用包装器方法,因为它遵循 Demeter 法则。但是,这似乎并不是每种情况下的最佳选择。

首先,许多内部对象的方法可能与 main class 无关,因此让 main class 为每个方法实现包装器没有任何意义,这很可能会破坏单一职责原则。此外,如果内部对象被用于大量其他 classes 的组合,所有这些都需要做同样的事情,这将导致大量不必要的代码重复,使您的代码更不枯燥。

我的第一直觉是有一个简单的 getBook() 方法,可以访问这本书以直接操作这些方法。把书从书架上拿下来翻页比让书架为你翻书页更有意义。然而,这似乎打破了封装和得墨忒耳法则。如果我要使本书变量 public 最终化,这同样适用。

我错过了什么吗?还是使事情过于复杂?我似乎无法解决这个问题,所以非常感谢您的帮助。

在这种情况下,您很可能只有书,而不是书架上的一本书。对我来说,return 通过书架上唯一的 id 一本特定的书并对其进行操作是非常有意义的。

在那种情况下,我会避免 return 收集会违反封装和 Demeter 法则的书籍。

因此,例如:

public class Shelf {
    private Map<Long, Book> books = new HashMap();

    // Class Code

    public Book getBook(Long id) {
       return books.get(id);
    }
}

这样的事情不会破坏封装,因为您没有暴露 class 的内部结构。如果您希望使用列表而不是地图,则 class 之外的任何地方都不会受到更改的影响。

而且,在这种情况下,return 这本书比在 Shelf class 中创建方法 turnPage() 更有意义。这与 属性 name in Book 中的字符串类型相同。您不会在 Book 中创建方法 nameSubstring() 只是为了对 name 进行操作,对吗?那么为什么要在 shelf 中创建一个 turnPage() 只是为了对 Book 进行操作?