简体   繁体   English

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

[英]Composition best practice with internal object instantiation

I am playing around with composition and had a question. 我在玩作曲,有一个问题。 Say I have a Fruit and Apple classes where apple is a passthrough to a fruit 说我有一个FruitApple课程,其中apple是水果的传递

public class Apple {
    Fruit fruit;
}

Fruit has a bunch of member fields such as skin , color etc. What is the best practice when we instantiate an Apple object? 水果具有许多成员字段,例如skincolor等。实例化Apple对象时的最佳实践是什么? Should I construct the fruit object internally without exposing any indication that the Apple contains a Fruit object? 我是否应该在内部构造fruit对象而没有任何迹象表明苹果包含水果对象? ie when constructing the Apple object, I call apple.setColor() which sets the fruit.setColor() property internally. 即,在构造Apple对象时,我调用apple.setColor() ,它在内部设置了fruit.setColor()属性。 Or, should I construct the full fruit object and during the apple instantiation, pass in the fruit object fully constructed? 还是应该构造完整的fruit对象,并在apple实例化过程中传递完全构造的fruit对象?

It really depends on how you are modeling your problem. 这实际上取决于您如何建模问题。 But I think paying attention to encapsulation principle of OOP would help us. 但是我认为关注OOP的封装原理会有所帮助。 Encapsulation wants us to hide information about an object within itself, or, in other words give each object responsibility of performing its own actions. 封装要求我们在其内部隐藏有关对象的信息,或者换句话说,赋予每个对象执行其自己的动作的责任。

Back to your question, first let us consider the case in which Fruit object is only an underlying data structure (ie Apple object is a complete superset of Fruit in responsibilities). 回到您的问题,首先让我们考虑“ Fruit对象只是基础数据结构的情况(即Apple对象是“ Fruit ”职责的完整超集)。 In this case, if you ask developers to construct the Fruit object for you and pass it along, you are exposing your internal responsibilities, and you may let the developer access to unwanted data or behavior. 在这种情况下,如果您要求开发人员为您构造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

It is now obvious that in some cases, the above example is exactly the thing you want to do. 现在很明显,在某些情况下,上面的示例正是您要执行的操作。 Consider now the composition pattern (see here ). 现在考虑合成模式(请参阅此处 )。 In composition you have a container which is not anticipated to encapsulate the responsibilities for its contained elements. 在组合中,您有一个容器 ,预计该容器不会封装其所包含元素的职责。

A very simple example can be a university course, in which some students enroll and has an instructor: 一个非常简单的示例可以是一门大学课程,其中一些学生报名并有一名讲师:

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

Here, it is not the Course object responsibility to expose instructor or students behaviors. 在这里,暴露老师或学生的行为不是Course对象的责任。 Instead, the container object may have getInstructor() and setInstructor() methods and let the developer decide about the contained elements in the composition. 相反,容器对象可以具有getInstructor()setInstructor()方法,并让开发人员确定合成中包含的元素。

Seems weird to have a Fruit inside an Apple. 好像在苹果里面有水果很奇怪。 I would use inheritance in this case. 在这种情况下,我将使用继承。 Or at least have Apple implement a Fruit interface and hide the delegate member. 或者至少让Apple实现了Fruit接口并隐藏委托成员。 So for constructing the Fruit member, that means: Do it internally inside the Apple constructor. 因此,对于构造Fruit成员而言,这意味着:在Apple构造函数内部进行此操作。 This is because of the is-a relationship between the Apple and Fruit concepts. 这是由于Apple和Fruit概念之间的is-关系。

In other cases it might be usefull to pass a pre constructed instance for the member in the constructor. 在其他情况下,为构造函数中的成员传递预构造实例可能会很有用。 That would be the case eg if more apples refer to the same fruit instance. 例如,如果更多的苹果引用了相同的水果实例,情况就是这样。 In general that would be more of a has-a or uses relation between Apple and Fruit 通常,Apple和Fruit之间更像是has-a或use关系

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM