使用组合访问对象方法?

时间:2015-11-01 08:50:09

标签: oop composition

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

这是一个非常广泛的主题,但我会举一个例子,只是为了让事情变得清晰。代码用java编写,但我相信这个问题几乎适用于任何使用OOP的语言。

Class Shelf {
    private Book book;
}

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

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

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

我的第一直觉是拥有一个简单的getBook()方法,以便访问该书以直接操作方法。将书籍从书架上翻开并转动页面更有意义,而不是告诉书架为您翻书。然而,这似乎打破了封装和德米特定律。如果我将书籍变量公之最终,这同样适用。

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

1 个答案:

答案 0 :(得分:2)

在这种情况下,很可能你会有书,而不是书架上的一本书。对于我来说,通过一个独特的书架来回复一本特定的书籍并对其进行操作是完全合理的。

在这种情况下,我会避免返回那些违反封装和Demeter法的书籍集。

所以,例如:

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

    // Class Code

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

这样的事情不会破坏封装,因为你没有暴露类的内部。如果您希望使用列表而不是地图,那么课外不应该受到更改的影响。

而且,在这种情况下,返回书籍而不是在turnPage()类中创建方法Shelf是有意义的。如果你在name中有一个属性为Book的字符串,那就是一样的。您不会在nameSubstring()中创建方法Book只是为了对name进行操作,对吗?那你为什么要在货架上创建一个turnPage()来操作Book