内部对象实例化的组合最佳实践

时间:2015-11-07 22:44:45

标签: java inheritance composition

我正在玩作曲,并有一个问题。假设我有FruitApple个类,其中apple是水果的直通

public class Apple {
    Fruit fruit;
}

Fruit有许多成员字段,例如skincolor等。当我们实例化Apple对象时,最佳做法是什么?我应该在内部构造fruit对象而不暴露Apple包含Fruit对象的任何迹象吗?即在构造Apple对象时,我调用apple.setColor()在内部设置fruit.setColor()属性。或者,我应该构造完整的fruit对象,并在apple实例化期间传入完全构造的fruit对象吗?

2 个答案:

答案 0 :(得分:2)

这实际上取决于您对问题的建模方式。但我认为关注OOP的封装原则会对我们有所帮助。封装要求我们隐藏有关对象内部的信息,换句话说,让每个对象都有责任执行自己的操作。

回到你的问题,首先让我们考虑Fruit对象只是一个底层数据结构的情况(即Apple对象是责任中Fruit的完整超集。在这种情况下,如果您要求开发人员为您构建Fruit对象并将其传递给您,那么您将承担内部职责,并且您可以让开发人员访问不需要的数据或行为。

Fruit f = new Fruit();
f.doSomethingPrivate(); // This is not intended for an Apple to be set externally

Apple a = new Apple(f); // Now the Fruit object may not comply with Apple definition

现在很明显,在某些情况下,上面的示例正是您想要做的事情。现在考虑组合模式(参见here)。在组合中,您有一个容器,预计不会封装其包含元素的职责。

一个非常简单的例子可以是大学课程,其中一些学生注册并有一名教师:

public class Course {
    private Person instructor;
    private Person[] students;
}

在这里,公开讲师或学生行为不是Course对象的责任。相反,容器对象可能有getInstructor()setInstructor()方法,让开发人员决定组合中包含的元素。

答案 1 :(得分:0)

在Apple内部拥有Fruit似乎很奇怪。在这种情况下我会使用继承。或者至少让Apple实现一个Fruit接口并隐藏委托成员。因此,对于构造Fruit成员,这意味着:在Apple构造函数内部执行它。这是因为Apple和Fruit概念之间存在着一种关系。

在其他情况下,为构造函数中的成员传递预构造的实例可能很有用。就是这种情况,例如如果更多的苹果引用相同的水果实例。一般而言,这将更多地是苹果与水果之间的关系或使用关系