2010-01-26 82 views
17

作为一个组合设计如何可以不同于委托,在实施方面是否有任何区别。例如,下面的代码似乎在进行委派,因为用户不能访问组合对象(即“a”)而不使用b。因此,用户需要调用类b的接口,然后“类b”调用“类a”的相应接口进行委派。这有意义吗?组合与授权

Class A { 
friend class B; 
private: 
A(){}; //dont want user to instantiate this class object since it wont sense without any context. Just like a room with no house. 
void PrintStructure(){}; 
}; 

Class B{ 
public: 
void PrintStructure(){a.PrintStructure();} //delegate 

private: 
A a; //composition 
}; 

回答

31

术语“组合”通常用于对象建模作为“有-a”关系的表达式,并且是关联的形式(另一个是聚合)。这通常与“继承”(“是 - 一个”关系)形成对比。所以:

构图和聚合有什么区别?构图意味着如果没有父母的语境,孩子就不能存在。

例如,众议院有一个或多个房间。这是一个构图关系。删除房屋,房间也不复存在。众议院也有一些居民,是人的实例。这是一种聚合关系,因为这些人存在于该房屋的环境之外。

委托只不过是一个实现细节。一个类有一个描述其状态和行为的公共接口。如何实施是无关紧要的。它可以委托给其他对象或不。

你会注意到你的例子中的A和B都有相同的外部接口。这是更常见的是做这样的事情:

// this represents an interface 
class A { 
public: 
    virtual void printStructure() = 0; 
} 

与具体类:

class ConcreteA : A { 
public: 
    virtual void printStructure() { ... } 
} 

class DelegateA : A { 
public: 
    DelegateA(A& a) { this.a = a; } 
    virtual void printStructure() { a.printStructure(); } 
private: 
    A a; 
} 

原谅我大概C++的语法错误。我有点生疏。

+0

如果构图意味着在没有父类的上下文的情况下子不能存在,那么应该永远不允许用户创建组合类的对象?例如,我的雅致的例子是A类(朋友B类; private:A(){}; void PrintStructure(){}; };类B {public:void PrintStructure(){a.PrintStructure();} // delegate private:A a; //组合};现在B类具有类A.用户只能使用B类接口来改变A类行为,而B类应该将这些任务委托给A类函数。这个设计好吗? – 2010-01-26 03:01:21

+0

@Frank:朋友类是实现这种关系的一种方式。他们不是我赞成的。一个更优雅的解决方案是让Room的构造函数需要House的一个实例,然后它成为它的“父”。 – cletus 2010-01-26 03:04:26

+0

你如何在我的例子中编写类似的代码?此外,我不希望用户能够实例化A的对象,因为没有B的上下文对A进行任何操作都没有意义。 – 2010-01-26 03:12:49

7

有一对夫妇的差异我看到:

  • 代表团包括再出口的方法;在构图关系中,内部对象方法可能只能被私人使用而不会被重新暴露。
  • 组合通常意味着某种所有权语义,会影响对象的生命周期;父母对象“拥有”了孩子,而孩子没有太多理由独立存在。代表团没有这个含义。

您显示的代码使用委派和关联;该关联可能是构图,但是如果没有更广泛的上下文或关于对象的更多信息(当关联变成构图时它可能非常微妙和主观),很难说出。

+0

导出方法对于委托并不是必需的。来自维基百科:“在其最初的用法中,委托指的是依赖另一个对象来提供指定的一组功能。” – danben 2010-01-26 02:43:33

4

构图是关于对象之间的关系。

代表团关于将工作从一个对象传递到另一个对象。

这些实际上是不同的(但有时是相关的)问题。

你得到的是B由A组成(B指的是A)。 B还将其一种方法委托给A.但由于B对A的使用是私人的(完全封装在B的黑盒子里),所以我不会把B的使用称为“组合”。如果B类可以从B访问,那么我将使用“组合”。这里重要的是如果B的逻辑模型“具有-A”,那么在这种情况下,B以A的形式实现。因为这是一个实现涉及它可以被认为不是B的逻辑模型的一部分。也就是说,你可以聪明地谈论B,而不用谈论或关心A.

这就是说,这些东西对于PHB和UML建模工具来说真的很重要。或者,如果你正在学习设计模式。我不会太在意它。

[PHB => Pointy Haired Boss]

+0

这是否意味着在构图中组合的对象(在这种情况下“a”)必须公开?这样用户就可以访问使用b例如B b; b.a.PrintStructure(); //假设成员函数是公共的。 – 2010-01-26 04:14:35

+0

这里没有绝对的对与错。重要的是这些课程的意图。你不应该仅仅因为一些“构成”的概念就让B类的“a”成员公开。而是考虑“a”对使用B类实例的代码是否重要。如果使用B的代码需要达到“a”,那么B应该有一个方法(方法)来访问它。在你的例子中,“a”是私有的,所以它在B中的存在和使用完全隐藏在使用类B的代码中。这通常是件好事。 更多: http://en.wikipedia.org/wiki/Information_hiding http://en.wikipedia.org/wiki/Information_hiding http://en.wikipedia.org/wiki/Object_composition – rickmode 2010-01-26 04:49:25

+0

谢谢,我开始了一个不同的线程,如果在合成中返回一个私有成员引用OOP 。在我的情况下,B必须有A,然而用户需要设置A的一些特性,这将需要他/她以某种方式到达A.我不想使用委托,要么我需要在每种方法中公开B中的方法在一个。 – 2010-01-26 18:39:55