Oop 使用组合访问对象方法?

Oop 使用组合访问对象方法?,oop,composition,Oop,Composition,这可能是一件非常简单的事情,但我似乎无法独自解决这个问题。当使用组合时,访问“内部对象”方法的最佳方式是什么?我所能想到的每一种方式似乎都违反了OO原则 这是一个非常宽泛的话题,但我会举一个例子,让事情尽可能清楚。代码是用java编写的,但我相信这个问题适用于几乎所有使用OOP的语言 Class Shelf { private Book book; } Class Book { public void turnPage() { //do stuff }

这可能是一件非常简单的事情,但我似乎无法独自解决这个问题。当使用组合时,访问“内部对象”方法的最佳方式是什么?我所能想到的每一种方式似乎都违反了OO原则

这是一个非常宽泛的话题,但我会举一个例子,让事情尽可能清楚。代码是用java编写的,但我相信这个问题适用于几乎所有使用OOP的语言

Class Shelf {
    private Book book;
}

Class Book {
    public void turnPage() {
        //do stuff
    }
}
当您只能访问Shelf对象时,访问Book方法的最佳方式是什么?我读过的一些地方建议将包装方法放在书架上,因为它遵循德米特定律。然而,这似乎不是所有情况下的最佳选择

首先,许多内部对象的方法可能与主类无关,因此让主类为每个方法实现包装器没有任何意义,而且很可能会打破单一责任原则。此外,如果在大量其他类中使用内部对象进行组合,所有这些类都需要执行相同的操作,那么它将导致大量不必要的代码复制,从而使代码不那么枯燥

我的第一个直觉是拥有一个简单的getBook()方法,允许访问该书以直接操作这些方法。从书架上取下一本书并翻页比让书架为你翻页更有意义。然而,这似乎打破了封装和德米特定律。如果我要将book变量公开为final,同样适用


我错过什么了吗?还是过度复杂化?我似乎无法理解这一点,因此我非常感谢您的帮助。

在这种情况下,您很可能有书,而书架上没有一本书。对于我来说,用书架上唯一的id返回一本特定的书并对其进行操作是非常有意义的

在这种情况下,我会避免退回藏书,因为这将违反封装和德米特定律

例如:

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

    // Class Code

    public Book getBook(Long id) {
       return books.get(id);
    }
}
公共类工具架{
私有地图册=新HashMap();
//类别代码
公共图书getBook(长id){
归还图书。获取(id);
}
}
这样的东西不会破坏封装,因为您不会公开类的内部。如果您希望使用列表而不是映射,则类之外的任何地方都不应受到更改的影响


在这种情况下,还书而不是在
Shelf
类中创建方法
turnPage()
,是有意义的。这与在
Book
中有一个字符串类型的属性
name
是一样的。您不会在
Book
中创建一个方法
nameSubstring()
,只是为了对
name
进行操作,对吗?那么,为什么你要在书架上创建一个
翻页()
来操作
这本书呢?

虽然我同意这一点,但这是否仍然违反了德米特定律?如果它是一个对象而不是一个对象的集合,那么同样的情况是否也适用?我不觉得它违反了LoD,因为您没有公开
Shelf
的内部,您只是使用
Shelf
作为访问器,这是主要思想。可以将书籍作为查询
书架
的结果返回,而不是公开内部内容