区分委托、组合和聚合(Java OO设计)

时间:2022-06-11 20:45:46

I am facing a continuing problem distinguishing delegation, composition and aggregation from each other, and identifying the cases where it's the best to use one over the other.

我面对的是一个持续存在的问题,区分委托、组合和聚合,并识别出最好使用其中一个的情况。

I have consulted a Java OO Analysis and Design book, but my confusion still remains. The main explanation is this:

我咨询过Java OO分析和设计书籍,但我的困惑仍然存在。主要的解释是:

Delegation: When my object uses another object's functionality as is without changing it.

委托:当我的对象使用另一个对象的功能时。

Composition: My object consists of other objects which in turn cannot exist after my object is destroyed-garbage collected.

组合:我的对象由其他对象组成,而这些对象在我的对象被销毁后又不能存在——垃圾收集。

Aggregation: My object consists of other objects which can live even after my object is destroyed.

聚合:我的对象由其他对象组成,即使在我的对象被销毁后,这些对象仍然可以生存。

Is it possible to have a few simple examples demonstrating each case, and the reasoning behind them? How else can these examples be demonstrated other than my object simply having a reference to another object(s)?

是否可能有一些简单的例子来说明每个案例,以及背后的原因?除了对象引用另一个对象之外,这些示例还有什么可演示的呢?

4 个解决方案

#1


48  

Your object would reference another object(s) in all three cases. The difference lies in behavior and / or lifecycle of referenced objects. Some examples:

在这三种情况下,对象都会引用另一个对象。区别在于被引用对象的行为和/或生命周期。一些例子:

  1. Composition: House contains one or more rooms. Room's lifetime is controlled by House as Room will not exist without House.

    构图:房子包含一个或多个房间。房间的寿命是由房子控制的,没有房子就没有房间。

  2. Aggregation: Toy house built from blocks. You can disassemble it but blocks will remain.

    集合:积木搭成的玩具屋。你可以把它拆开,但积木会留下来。

  3. Delegation: Your boss asked you to get him a coffee, you've had an intern do it for you instead. Delegation is not a type of association (like composition / aggregation are). The latter two have been discussed on Stack Overflow many times

    代表团:你的老板让你给他弄杯咖啡,你让一个实习生替你做。委托不是一种关联类型(如组合/聚合)。后两者在栈溢出上已经讨论了很多次

In the comment you ask how the implementation would differ in each case, observing that in all cases we invoke methods on the releated objects. It's true that in each case we would have code such as

在注释中,您会询问实现在每种情况下会有什么不同,注意到在所有情况下我们都调用被释放对象上的方法。的确,在每种情况下,我们都会有这样的代码。

myRoom.doWork();

myBlock.doWork();

myMinion.doWork();

but the differences lie in the life-cycle and cardinality of the related objects.

但区别在于相关对象的生命周期和基数。

For the Component, the Rooms come into existence when the House is created. So we might create them in the constructor of the House.

对于部件来说,房间是在房子被创造出来的时候产生的。我们可以在房子的构造函数中创建它们。

In the case of Association (I'll use Tyre and Car) Cars might add Tyres in their constructor, but later you may want to remove and change tyres. So you also have methods such as

在关联的情况下(我将使用轮胎和汽车)汽车可能会在它们的构造中添加轮胎,但是稍后您可能想要移除和更换轮胎。你还有一些方法

 removeTyre(FrontLeft)
 addNewTyre(aTyre, BackRight)

And it's quite likely that the aTyre object came from a Factory - we didn't new it in any of the Car's methods.

很有可能那个类型对象来自于一个工厂——我们没有在汽车的任何方法中使用它。

In the case of Delegation, you might not even have a member variable to hold the delegate

对于委托,您甚至可能没有一个成员变量来保存委托

 resourcingPool().getIntern().getCoffee(SkinnyLatte, workstation 7);

the relationship between the objects lasts only as long as the intern is fetching the coffee. Then it returns to the resource pool.

只有当实习生在取咖啡时,这些物品之间的关系才会持续。然后返回资源池。

#2


49  

Delegation

public class A {
  private B b = new B();

  public void methodA() {
    b.methodB();
  }
}

When clients of A call methodA, class A delegates the call to B's methodB.

当调用methodA的客户端时,class A将调用委托给B的methodB。

Rationale. Class A exposes behaviours that belong elsewhere. This can happen in single-inheritance languages where class A inherits from one class, but its clients need behaviours that are implemented in a different class. Further study.

基本原理。A类暴露了属于其他地方的行为。这可以在单继承语言中实现,其中类A继承了一个类,但是它的客户端需要在另一个类中实现的行为。进一步的研究。

Hybrid Delegation

public class A {
  private B b = new B();

  public void methodA() {
    b.methodB( this );
  }
}

The difference between delegation that involves simple forwarding and delegation that acts as a substitute for inheritance is that the callee must accept a parameter of the caller, exemplified as:

涉及简单转发的委托和作为继承替代的委托之间的区别在于,被调用者必须接受调用者的一个参数,例如:

    b.methodB( this );

Rationale. Allows class B instances to use functionality available from class A, just as class B would if it inherited from class A--but without inheritance. Further study.

基本原理。允许类B实例使用类A可用的功能,就像类B从类A继承时使用的功能一样——但没有继承。进一步的研究。

Composition

public class A {
  private B b = new B();

  public A() {
  }
}

Once no more references to a particular instance of class A exist, its instance of class B is destroyed.

一旦不再存在对类a的特定实例的引用,它的类B的实例就会被销毁。

Rationale. Allows classes to define behaviours and attributes in a modular fashion. Further study.

基本原理。允许类以模块化的方式定义行为和属性。进一步的研究。

Aggregation

public class A {
  private B b;

  public A( B b ) {
    this.b = b;
  }
}

public class C {
  private B b = new B();

  public C() {
    A a = new A( this.b );
  }
}

Once there are no more references to a particular instance of class A, its instance of class B will not be destroyed. In this example, both A and C must be garbage collected before B will be destroyed.

一旦不再有对类a的特定实例的引用,它的类B的实例将不会被销毁。在本例中,必须在B被销毁之前收集A和C。

Rationale. Allows instances to reuse objects. Further study.

基本原理。允许实例重用对象。进一步的研究。

Demonstration Without References

The names given to these simple patterns are defined by their referential relationships.

这些简单模式的名称由它们的引用关系定义。

#3


15  

Your book explains quite good so let me elaborate and provide you some examples.

你的书解释得很好,让我来详细说明并给你一些例子。

delegation: When my object uses another object's functionality as is without changing it.

委托:当我的对象使用另一个对象的功能时。

Sometime a class may logically need to be big. But big class is not a good coding pratice. Also sometime, some functionalities of a class may be implementable in more than one way and you may want to change that some time.

有时候一个类在逻辑上可能需要很大。但是大类并不是一个好的编程实践。有时,某个类的某些功能可能在不止一种方式上是可实现的,您可能想要在一段时间内改变它。


class FeatureHolder {
 void feature() {
  // Big implementation of the feature that you dont want to put in the class Big
 }
}

class Big {
 private FeatureHolder FH = new FeatureHolder();

 void feature() {
  // Delegate to FeatureHolder.
  FH.feature();
 }

 //.. Other features
}

From the above example, Big.feature() call feature of FH as is without changing it. This way, the class Big does not need to contain the implementation of the feature (separation of labour). Also, feature() can implement differently by other class like "NewFeatureHolder" and Big may choose to use the new feature holder instead.

从上面的示例中可以看出,Big.feature()调用FH的特性是不变的。这样,阶级大就不需要包含实施特征(劳动分工)。而且,feature()可以通过其他类实现不同的实现,比如“NewFeatureHolder”,Big可以选择使用新的特性holder。

composition: My object consists of other objects which in turn cannot exist after my object is destryed-garbage collected.

组合:我的对象由其他对象组成,而这些对象在我的对象被destrygarbage collect之后又不能存在。

aggregation: My object consists of other objects which can live even after my object is destroyed.

聚合:我的对象由其他对象组成,即使在我的对象被销毁后,这些对象仍然可以生存。

Technially, Composition is "part of" and Aggregation is "refer to" relationship. Your arms are part of you. If you no longer live, your arm will die too. Your cloth is not part of you but you have them; as you can guest, your cloth does not go with you.

从技术上说,组成是“部分”,聚集是“指”关系。你的手臂是你的一部分。如果你不再活着,你的手臂也会死去。你的布不是你的一部分,但你拥有它们;如你所料,你的布和你不相配。

In programming, some objects are part of another object and they have no logical meaning without it. For example, a button is composed into a window frame. If a frame is closed, the button has no reason to be around anymore (Composition). A button may have reference to a database (like to refreash data); when the button is eliminated, the database may still be around (Aggregation).

在编程中,有些对象是另一个对象的一部分,没有它,它们就没有逻辑意义。例如,一个按钮被组合成一个窗框。如果一个帧被关闭,按钮就没有理由再出现了(合成)。一个按钮可以引用数据库(比如刷新数据);当按钮被删除时,数据库可能仍然存在(聚合)。

Sorry for my English, Hope this helps

为我的英语感到抱歉,希望这能有所帮助

#4


1  

1) Delegation: Man-driver-car example. A Man bought a car. But that man does not know to drive the car. So he will appoint a driver who knows driving a car. So the Man class wants to perform a transportation using car. But it does not have the interacting- functionality/compatibility with car. So he uses a class which has compatibility with car that is driver which is compatible with man class. Assuming that driver can understand what man says

1)代表团:Man-driver-car例子。一个男人买了一辆车。但是那个人不知道开车。所以他会指定一个会开车的司机。所以男人阶层想要用汽车进行交通。但它没有与汽车的交互功能/兼容性。所以他使用了一个与car兼容的类,它是与man类兼容的驱动程序。假设那个司机能听懂别人说的话

2) Composition: Car simulation is a routine example. To make a car move, wheel rotates. Car class using wheel class rotate functinality as part of its move function, where as wheel is part of car.

2)作文:汽车模拟是一个常规的例子。要使汽车运动,车轮要转动。汽车类使用车轮类旋转功能作为其移动功能的一部分,如车轮是汽车的一部分。

3) Aggregation: Car and its colour. Car class object ferrari will have a colour class object red. But colour class object red can be there as individual class, when user search happens with a specification of red colour.

3)聚合:汽车及其颜色。汽车类对象法拉利将有一个颜色类对象红色。但是颜色类对象红色可以作为单独的类存在,当用户搜索使用红色的规范时。

#1


48  

Your object would reference another object(s) in all three cases. The difference lies in behavior and / or lifecycle of referenced objects. Some examples:

在这三种情况下,对象都会引用另一个对象。区别在于被引用对象的行为和/或生命周期。一些例子:

  1. Composition: House contains one or more rooms. Room's lifetime is controlled by House as Room will not exist without House.

    构图:房子包含一个或多个房间。房间的寿命是由房子控制的,没有房子就没有房间。

  2. Aggregation: Toy house built from blocks. You can disassemble it but blocks will remain.

    集合:积木搭成的玩具屋。你可以把它拆开,但积木会留下来。

  3. Delegation: Your boss asked you to get him a coffee, you've had an intern do it for you instead. Delegation is not a type of association (like composition / aggregation are). The latter two have been discussed on Stack Overflow many times

    代表团:你的老板让你给他弄杯咖啡,你让一个实习生替你做。委托不是一种关联类型(如组合/聚合)。后两者在栈溢出上已经讨论了很多次

In the comment you ask how the implementation would differ in each case, observing that in all cases we invoke methods on the releated objects. It's true that in each case we would have code such as

在注释中,您会询问实现在每种情况下会有什么不同,注意到在所有情况下我们都调用被释放对象上的方法。的确,在每种情况下,我们都会有这样的代码。

myRoom.doWork();

myBlock.doWork();

myMinion.doWork();

but the differences lie in the life-cycle and cardinality of the related objects.

但区别在于相关对象的生命周期和基数。

For the Component, the Rooms come into existence when the House is created. So we might create them in the constructor of the House.

对于部件来说,房间是在房子被创造出来的时候产生的。我们可以在房子的构造函数中创建它们。

In the case of Association (I'll use Tyre and Car) Cars might add Tyres in their constructor, but later you may want to remove and change tyres. So you also have methods such as

在关联的情况下(我将使用轮胎和汽车)汽车可能会在它们的构造中添加轮胎,但是稍后您可能想要移除和更换轮胎。你还有一些方法

 removeTyre(FrontLeft)
 addNewTyre(aTyre, BackRight)

And it's quite likely that the aTyre object came from a Factory - we didn't new it in any of the Car's methods.

很有可能那个类型对象来自于一个工厂——我们没有在汽车的任何方法中使用它。

In the case of Delegation, you might not even have a member variable to hold the delegate

对于委托,您甚至可能没有一个成员变量来保存委托

 resourcingPool().getIntern().getCoffee(SkinnyLatte, workstation 7);

the relationship between the objects lasts only as long as the intern is fetching the coffee. Then it returns to the resource pool.

只有当实习生在取咖啡时,这些物品之间的关系才会持续。然后返回资源池。

#2


49  

Delegation

public class A {
  private B b = new B();

  public void methodA() {
    b.methodB();
  }
}

When clients of A call methodA, class A delegates the call to B's methodB.

当调用methodA的客户端时,class A将调用委托给B的methodB。

Rationale. Class A exposes behaviours that belong elsewhere. This can happen in single-inheritance languages where class A inherits from one class, but its clients need behaviours that are implemented in a different class. Further study.

基本原理。A类暴露了属于其他地方的行为。这可以在单继承语言中实现,其中类A继承了一个类,但是它的客户端需要在另一个类中实现的行为。进一步的研究。

Hybrid Delegation

public class A {
  private B b = new B();

  public void methodA() {
    b.methodB( this );
  }
}

The difference between delegation that involves simple forwarding and delegation that acts as a substitute for inheritance is that the callee must accept a parameter of the caller, exemplified as:

涉及简单转发的委托和作为继承替代的委托之间的区别在于,被调用者必须接受调用者的一个参数,例如:

    b.methodB( this );

Rationale. Allows class B instances to use functionality available from class A, just as class B would if it inherited from class A--but without inheritance. Further study.

基本原理。允许类B实例使用类A可用的功能,就像类B从类A继承时使用的功能一样——但没有继承。进一步的研究。

Composition

public class A {
  private B b = new B();

  public A() {
  }
}

Once no more references to a particular instance of class A exist, its instance of class B is destroyed.

一旦不再存在对类a的特定实例的引用,它的类B的实例就会被销毁。

Rationale. Allows classes to define behaviours and attributes in a modular fashion. Further study.

基本原理。允许类以模块化的方式定义行为和属性。进一步的研究。

Aggregation

public class A {
  private B b;

  public A( B b ) {
    this.b = b;
  }
}

public class C {
  private B b = new B();

  public C() {
    A a = new A( this.b );
  }
}

Once there are no more references to a particular instance of class A, its instance of class B will not be destroyed. In this example, both A and C must be garbage collected before B will be destroyed.

一旦不再有对类a的特定实例的引用,它的类B的实例将不会被销毁。在本例中,必须在B被销毁之前收集A和C。

Rationale. Allows instances to reuse objects. Further study.

基本原理。允许实例重用对象。进一步的研究。

Demonstration Without References

The names given to these simple patterns are defined by their referential relationships.

这些简单模式的名称由它们的引用关系定义。

#3


15  

Your book explains quite good so let me elaborate and provide you some examples.

你的书解释得很好,让我来详细说明并给你一些例子。

delegation: When my object uses another object's functionality as is without changing it.

委托:当我的对象使用另一个对象的功能时。

Sometime a class may logically need to be big. But big class is not a good coding pratice. Also sometime, some functionalities of a class may be implementable in more than one way and you may want to change that some time.

有时候一个类在逻辑上可能需要很大。但是大类并不是一个好的编程实践。有时,某个类的某些功能可能在不止一种方式上是可实现的,您可能想要在一段时间内改变它。


class FeatureHolder {
 void feature() {
  // Big implementation of the feature that you dont want to put in the class Big
 }
}

class Big {
 private FeatureHolder FH = new FeatureHolder();

 void feature() {
  // Delegate to FeatureHolder.
  FH.feature();
 }

 //.. Other features
}

From the above example, Big.feature() call feature of FH as is without changing it. This way, the class Big does not need to contain the implementation of the feature (separation of labour). Also, feature() can implement differently by other class like "NewFeatureHolder" and Big may choose to use the new feature holder instead.

从上面的示例中可以看出,Big.feature()调用FH的特性是不变的。这样,阶级大就不需要包含实施特征(劳动分工)。而且,feature()可以通过其他类实现不同的实现,比如“NewFeatureHolder”,Big可以选择使用新的特性holder。

composition: My object consists of other objects which in turn cannot exist after my object is destryed-garbage collected.

组合:我的对象由其他对象组成,而这些对象在我的对象被destrygarbage collect之后又不能存在。

aggregation: My object consists of other objects which can live even after my object is destroyed.

聚合:我的对象由其他对象组成,即使在我的对象被销毁后,这些对象仍然可以生存。

Technially, Composition is "part of" and Aggregation is "refer to" relationship. Your arms are part of you. If you no longer live, your arm will die too. Your cloth is not part of you but you have them; as you can guest, your cloth does not go with you.

从技术上说,组成是“部分”,聚集是“指”关系。你的手臂是你的一部分。如果你不再活着,你的手臂也会死去。你的布不是你的一部分,但你拥有它们;如你所料,你的布和你不相配。

In programming, some objects are part of another object and they have no logical meaning without it. For example, a button is composed into a window frame. If a frame is closed, the button has no reason to be around anymore (Composition). A button may have reference to a database (like to refreash data); when the button is eliminated, the database may still be around (Aggregation).

在编程中,有些对象是另一个对象的一部分,没有它,它们就没有逻辑意义。例如,一个按钮被组合成一个窗框。如果一个帧被关闭,按钮就没有理由再出现了(合成)。一个按钮可以引用数据库(比如刷新数据);当按钮被删除时,数据库可能仍然存在(聚合)。

Sorry for my English, Hope this helps

为我的英语感到抱歉,希望这能有所帮助

#4


1  

1) Delegation: Man-driver-car example. A Man bought a car. But that man does not know to drive the car. So he will appoint a driver who knows driving a car. So the Man class wants to perform a transportation using car. But it does not have the interacting- functionality/compatibility with car. So he uses a class which has compatibility with car that is driver which is compatible with man class. Assuming that driver can understand what man says

1)代表团:Man-driver-car例子。一个男人买了一辆车。但是那个人不知道开车。所以他会指定一个会开车的司机。所以男人阶层想要用汽车进行交通。但它没有与汽车的交互功能/兼容性。所以他使用了一个与car兼容的类,它是与man类兼容的驱动程序。假设那个司机能听懂别人说的话

2) Composition: Car simulation is a routine example. To make a car move, wheel rotates. Car class using wheel class rotate functinality as part of its move function, where as wheel is part of car.

2)作文:汽车模拟是一个常规的例子。要使汽车运动,车轮要转动。汽车类使用车轮类旋转功能作为其移动功能的一部分,如车轮是汽车的一部分。

3) Aggregation: Car and its colour. Car class object ferrari will have a colour class object red. But colour class object red can be there as individual class, when user search happens with a specification of red colour.

3)聚合:汽车及其颜色。汽车类对象法拉利将有一个颜色类对象红色。但是颜色类对象红色可以作为单独的类存在,当用户搜索使用红色的规范时。