区分委派,组合和聚合(Java OO设计)

时间:2009-09-05 22:39:38

标签: java oop aggregation composition delegation

我面临着一个持续的问题,即将委派,组合和聚合彼此区分开来,并确定最好使用一个在另一个之上的情况。

我已经查阅过Java OO分析和设计书籍,但我的困惑仍然存在。主要解释如下:

委派:当我的对象使用其他对象的功能而不改变它时。

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

聚合:我的对象包含其他对象,即使在我的对象被销毁之后也可以存活。

是否可以通过几个简单的例子来说明每个案例,以及它们背后的原因?除了我的对象只是引用另一个对象之外,还能展示这些例子吗?

5 个答案:

答案 0 :(得分:54)

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

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

A的客户致电methodA时,课程A 委派B的{​​{1}}的来电。

理由。 A类暴露属于其他地方的行为。这可能发生在单继承语言中,其中类A继承自一个类,但其客户端需要在不同类中实现的行为。 Further study

混合代表团

methodB

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

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

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

基本原理。允许类 b.methodB( this ); 实例使用类B中提供的功能,就像类A从类B继承一样} - 但没有继承。 Further study

的组合物

A

一旦不再有对类public class A { private B b = new B(); public A() { } } 的特定实例的引用,就会销毁它的类A的实例。

原理。允许类以模块化方式定义行为和属性。 Further study

聚合

B

一旦没有对类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 ); } } 的特定实例的更多引用,其类A的实例将不会被销毁。在此示例中,BA必须在C被销毁之前进行垃圾回收。

原理。允许实例重用对象。 Further study

没有参考的演示

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

答案 1 :(得分:50)

在所有三种情况下,您的对象都会引用另一个对象。不同之处在于引用对象的行为和/或生命周期。一些例子:

  1. 组成:房子包含一个或多个房间。房间的寿命由House控制,因为没有House,房间将不存在。

  2. 聚合:用积木建造的玩具屋。你可以反汇编它,但会保留块。

  3. 代表团:你的老板让你给他一杯咖啡,你有一个实习生代替你。委托不是一种关联(如组合/聚合)。后两者已在Stack Overflow many times

  4. 上讨论过

    在评论中,您询问每种情况下实现的不同之处,观察在所有情况下我们都会在相关对象上调用方法。确实,在每种情况下我们都会有代码,例如

    myRoom.doWork();
    
    myBlock.doWork();
    
    myMinion.doWork();
    

    但不同之处在于相关对象的生命周期和基数。

    对于组件,房间在创建房屋时就会存在。所以我们可以在House的构造函数中创建它们。

    在协会(我将使用轮胎和汽车)的情况下,汽车可能会在他们的构造中添加轮胎,但稍后您可能想要移除和更换轮胎。所以你也有像

    这样的方法
     removeTyre(FrontLeft)
     addNewTyre(aTyre, BackRight)
    

    aTyre对象很可能来自工厂 - 我们在任何Car的方法中都没有new它。

    在委托的情况下,您甚至可能没有成员变量来保存委托

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

    只要实习生拿取咖啡,对象之间的关系就会持续。然后它返回资源池。

答案 2 :(得分:17)

你的书解释得非常好,所以让我详细说明并提供一些例子。

委托:当我的对象使用其他对象的功能而不改变它时。

某个时候某个课程在逻辑上可能需要很大。但大班不是一个好的编码实践。有时,某个类的某些功能可能以多种方式实现,您可能希望在一段时间内进行更改。


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
}

从上面的例子中,FH的Big.feature()调用功能不会改变它。这样,类Big就不需要包含该功能的实现(劳动分离)。此外,feature()可以通过其他类(如“NewFeatureHolder”)以不同方式实现,Big可以选择使用新的功能持有者。

组成:我的对象由其他对象组成,而这些对象在我的对象被描述后仍然不能存在 - 垃圾收集。

聚合:我的对象包含其他对象,即使在我的对象被销毁之后也可以存活。

从技术上讲,组合是“一部分”而聚合是“参照”关系。你的手臂是你的一部分。如果你不再活着,你的手臂也会死亡。你的衣服不是你的一部分,但你拥有它们;因为你可以做客,你的衣服不跟你一起去。

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

对不起我的英语,希望这有帮助

答案 3 :(得分:1)

1)代表团:Man-driver-car示例。一个男人买了一辆车。但那个男人不知道开车。所以他会指定一个知道驾驶汽车的司机。所以Man类想要用汽车进行运输。但它没有与汽车的互动功能/兼容性。因此他使用与汽车兼容的类,这是与man类兼容的驱动程序。假设司机能够理解男人说的话

2)组成:汽车模拟是一个常规的例子。为了使汽车移动,车轮旋转。使用轮类的汽车类旋转功能性作为其移动功能的一部分,其中轮子是汽车的一部分。

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

答案 4 :(得分:0)

我可以用很简单的一句话说:

委托是:当您不想更改行为时,将行为委托给其他类。我所说的是运行时的变化。例如,您将驾驶员委派给驾驶员在驾驶时不会改变的汽车等级。

组成为::当您要使用在运行时可能会更改的一类类(一个或多个类,实现一个接口)的行为时。但您应该考虑这些类与主类(例如旅馆的房间)不能同时存在。如果您删除旅馆,旅馆的所有房间将不存在。

聚集是:与组成相同,但类可以不存在主类而存在。