【问题标题】:Accessing object methods with composition?使用组合访问对象方法?
【发布时间】:2015-11-01 08:50:09
【问题描述】:

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

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

Class Shelf {
    private Book book;
}

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

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

首先,许多内部对象的方法可能与主类无关,因此让主类为每个方法实现包装器没有任何意义,而且很可能会破坏单一责任原则。此外,如果内部对象用于大量其他类中的组合,都需要做同样的事情,则会导致大量不必要的代码重复,从而使您的代码变得不那么 DRY。

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

我错过了什么吗?还是把事情复杂化了?我似乎无法理解这一点,所以我非常感谢一些帮助。

【问题讨论】:

    标签: oop composition


    【解决方案1】:

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

    在这种情况下,我会避免归还那些违反封装和得墨忒耳法则的书籍。

    所以,例如:

    public class Shelf {
        private Map<Long, Book> books = new HashMap();
    
        // Class Code
    
        public Book getBook(Long id) {
           return books.get(id);
        }
    }
    

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

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

    【讨论】:

    • 虽然我同意这一点,但这是否仍然违反得墨忒耳法则?如果它是单个对象而不是对象集合,这同样适用吗?
    • 我不觉得它违反了LoD,因为你没有暴露Shelf的内部,你只是使用Shelf作为访问器,这是主要思想。考虑将 Book 作为查询的结果返回到 Shelf,而不是暴露内部
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-14
    • 1970-01-01
    • 2012-02-27
    • 1970-01-01
    • 2013-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多