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

den*_*chr 57 java oop delegation composition aggregation

我面临着一个持续的问题,即彼此区分授权,组合和聚合,并确定最好使用一个而不是另一个的情况.

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

委派:当我的对象使用另一个对象的功能而不改变它.

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

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

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

Dav*_*vis 58

代表团

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

  public void methodA() {
    b.methodB();
  }
}
Run Code Online (Sandbox Code Playgroud)

当客户A来电methodA,类A 代表调用BmethodB.

基本原理.A类暴露属于其他地方的行为.这可能发生在单继承语言中,其中类A继承自一个类,但其客户端需要在不同类中实现的行为.进一步研究.

混合代表团

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

  public void methodA() {
    b.methodB( this );
  }
}
Run Code Online (Sandbox Code Playgroud)

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

    b.methodB( this );
Run Code Online (Sandbox Code Playgroud)

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

组成

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

  public A() {
  }
}
Run Code Online (Sandbox Code Playgroud)

一旦不再A存在对特定类实例的引用,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 );
  }
}
Run Code Online (Sandbox Code Playgroud)

一旦没有更多对类的特定实例的引用A,它的类实例B就不会被销毁.在这个例子中,AC前一定要收集的垃圾B将被销毁.

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

没有参考的示范

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


Chs*_*y76 52

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

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

  2. 聚合:从块建造的玩具屋.您可以拆卸它,但会保留块.

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

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

myRoom.doWork();

myBlock.doWork();

myMinion.doWork();
Run Code Online (Sandbox Code Playgroud)

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

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

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

 removeTyre(FrontLeft)
 addNewTyre(aTyre, BackRight)
Run Code Online (Sandbox Code Playgroud)

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

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

 resourcingPool().getIntern().getCoffee(SkinnyLatte, workstation 7);
Run Code Online (Sandbox Code Playgroud)

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

  • 或多或少。在委托的情况下,可以从其他地方获得引用(您甚至可以委托给静态方法);在组合的情况下,嵌套对象由父对象创建或在父对象的帮助下创建(因为它控制它们的生命周期);在聚合的情况下,会注入嵌套对象实例(通常在构造/初始化期间)。 (2认同)

Naw*_*Man 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
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

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