我正在玩作曲,并有一个问题。假设我有Fruit
和Apple
个类,其中apple
是水果的直通
public class Apple {
Fruit fruit;
}
Fruit有许多成员字段,例如skin
,color
等。当我们实例化Apple
对象时,最佳做法是什么?我应该在内部构造fruit
对象而不暴露Apple包含Fruit对象的任何迹象吗?即在构造Apple对象时,我调用apple.setColor()
在内部设置fruit.setColor()
属性。或者,我应该构造完整的fruit
对象,并在apple
实例化期间传入完全构造的fruit
对象吗?
答案 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概念之间存在着一种关系。
在其他情况下,为构造函数中的成员传递预构造的实例可能很有用。就是这种情况,例如如果更多的苹果引用相同的水果实例。一般而言,这将更多地是苹果与水果之间的关系或使用关系