内部对象实例化的组合最佳实践
Composition best practice with internal object instantiation
我正在研究作文,有一个问题。假设我有一个 Fruit
和 Apple
类,其中 apple
是水果
的直通
public class Apple {
Fruit fruit;
}
Fruit 有一堆成员字段,例如skin
、color
等。当我们实例化一个Apple
对象时,最佳实践是什么?我是否应该在内部构造 fruit
对象而不暴露 Apple 包含 Fruit 对象的任何迹象?即在构造 Apple 对象时,我调用 apple.setColor()
来在内部设置 fruit.setColor()
属性。或者,我应该构造完整的 fruit
对象并在 apple
实例化期间传入完全构造的 fruit
对象吗?
一个苹果里面有一个水果看起来很奇怪。在这种情况下我会使用继承。或者至少让 Apple 实现一个 Fruit 接口并隐藏委托成员。因此,对于构建 Fruit 成员,这意味着:在 Apple 构造函数内部执行。这是因为 Apple 和 Fruit 概念之间存在 is-a 关系。
在其他情况下,在构造函数中为成员传递预构造的实例可能会有用。情况就是这样,例如如果更多苹果指的是同一个水果实例。一般来说,Apple 和 Fruit
之间更像是 has-a 或 uses 关系
这实际上取决于您如何为问题建模。但是我认为关注 OOP 的 encapsulation 原则会对我们有所帮助。封装希望我们将有关对象的信息隐藏在自身内部,或者换句话说,让每个对象负责执行自己的操作。
回到你的问题,首先让我们考虑 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()
方法,让开发人员决定组合中包含的元素。
我正在研究作文,有一个问题。假设我有一个 Fruit
和 Apple
类,其中 apple
是水果
public class Apple {
Fruit fruit;
}
Fruit 有一堆成员字段,例如skin
、color
等。当我们实例化一个Apple
对象时,最佳实践是什么?我是否应该在内部构造 fruit
对象而不暴露 Apple 包含 Fruit 对象的任何迹象?即在构造 Apple 对象时,我调用 apple.setColor()
来在内部设置 fruit.setColor()
属性。或者,我应该构造完整的 fruit
对象并在 apple
实例化期间传入完全构造的 fruit
对象吗?
一个苹果里面有一个水果看起来很奇怪。在这种情况下我会使用继承。或者至少让 Apple 实现一个 Fruit 接口并隐藏委托成员。因此,对于构建 Fruit 成员,这意味着:在 Apple 构造函数内部执行。这是因为 Apple 和 Fruit 概念之间存在 is-a 关系。
在其他情况下,在构造函数中为成员传递预构造的实例可能会有用。情况就是这样,例如如果更多苹果指的是同一个水果实例。一般来说,Apple 和 Fruit
之间更像是 has-a 或 uses 关系这实际上取决于您如何为问题建模。但是我认为关注 OOP 的 encapsulation 原则会对我们有所帮助。封装希望我们将有关对象的信息隐藏在自身内部,或者换句话说,让每个对象负责执行自己的操作。
回到你的问题,首先让我们考虑 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()
方法,让开发人员决定组合中包含的元素。