2010-01-26 37 views
17

¿Hay alguna diferencia en términos de implementación, ya que un diseño de composición puede ser diferente de la delegación? Por ejemplo, el código siguiente parece estar haciendo delegación, ya que el usuario no puede acceder al objeto compuesto (es decir, "a") sin utilizar b. Por lo tanto, el usuario necesitaría invocar las interfaces de la clase b y luego la "clase b" invocaría las interfaces apropiadas de la "clase a", convirtiéndola en delegación. Esto tiene sentido ?Composición frente a Delegación

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 
}; 

Respuesta

31

El término "composición" se usa generalmente en términos de modelado de objetos como una expresión de una relación "tiene-a" y es una forma de asociación (otra es la agregación). Esto generalmente se contrasta con "herencia" (relación "es-a"). Entonces:

¿Cuál es la diferencia entre composición y agregación? La composición implica que el niño no puede existir sin el contexto del padre.

Por ejemplo, una casa tiene una o más habitaciones. Esa es una relación de composición. Eliminar la casa y las habitaciones también dejan de existir. Una casa también tiene un número de ocupantes, siendo ejemplos de persona. Esa es una relación de agregación porque esas personas existen fuera del contexto de esa casa.

La delegación no es más que un detalle de implementación. Una clase tiene una interfaz pública que describe su estado y comportamiento. Cómo se implementa eso es irrelevante. Podría delegar a otros objetos o no.

Observará que tanto A como B de su ejemplo tienen la misma interfaz externa. Es más común de hacer algo como esto:

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

con clases concretas:

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

y

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

Excuse My probablemente C++ errores de sintaxis. Estoy un poco oxidado.

+0

Si la composición implica que el niño no puede existir sin el contexto del padre, ¿no debería el usuario nunca crear un objeto de la clase compuesta? Por ejemplo, mi refinado, por ejemplo, sería clase A {amigo Clase B; privado: A() {}; void PrintStructure() {}; }; Clase B {public: void PrintStructure() {a.PrintStructure();} // delegate private: A a; // composición}; Ahora la clase B tiene clase A. Un usuario debe usar solo interfaces de clase B para cambiar el comportamiento de clase A y la clase B debe delegar tales tareas a funciones de clase A. ¿Este diseño es bueno? –

+0

@Frank: las clases de amigos son una forma de implementar este tipo de relación. Aunque no son un favor. Una solución más elegante es hacer que el constructor de Room requiera una instancia de House, que luego se convierte en su "padre". – cletus

+0

¿Cómo codificaría algo así en mi ejemplo? Además, no quiero que el usuario pueda crear una instancia de un objeto de A, ya que no tendría sentido realizar ninguna operación en A sin el contexto de B. –

7

Hay un par de diferencias que veo:

  • Delegación implica métodos re-exportación; en una relación de composición, los métodos de objetos internos pueden usarse solo en privado y no volver a exponerse.
  • La composición generalmente implica algún tipo de semántica de propiedad con implicaciones para el ciclo de vida del objeto; el objeto principal "posee" al niño y el niño no tiene muchas razones para existir por sí mismo. La delegación no tiene esta implicación.

El código que muestra utiliza delegación y asociación; la asociación puede ser composición, pero es difícil de decir sin un contexto más amplio o más información sobre los objetos (puede ser bastante sutil y subjetiva cuando una asociación se convierte en una composición).

+0

No es necesario exportar métodos para la delegación. De Wikipedia: "En su uso original, la delegación se refiere a un objeto que depende de otro para proporcionar un conjunto específico de funcionalidades". – danben

4

La composición se trata de las relaciones entre los objetos.

La delegación se trata de pasar el trabajo de un objeto a otro.

Estas son en realidad preocupaciones diferentes (pero a veces relacionadas).

Lo que tienes es B compuesto por A (B se refiere a A). B también delega su único método a A.

Pero como el uso de B de A es privado (completamente encapsulado dentro del recuadro negro de B), no llamaría al uso de B de una "composición". Usaría "composición" solo si se pudiera acceder a la clase A desde B. Lo importante aquí es si el modelo lógico de B "tiene-a" A.

En su caso, B se implementa en términos de A. Como esto es una preocupación de implementación puede considerarse como no parte del modelo lógico de B. Es decir, puede hablar inteligentemente acerca de B sin hablar ni preocuparse por A.

Dicho todo esto, esto solo es realmente importante para las herramientas de modelado de PHB y UML. O tal vez si estás estudiando Patrones de diseño. No me gustaría demasiado colgado en él.

[PHB => Pointy Haired Boss]

+0

¿Eso significa que en composición el objeto compuesto (en este caso "a") tiene que hacerse público? De esta forma, el usuario tendría acceso a a usando b e.g B b; b.a.PrintStructure(); // asumiendo que la función miembro es pública. –

+0

No hay absoluto correcto o incorrecto aquí. Lo que importa es la intención de las clases. No debe hacer público al miembro "a" de la clase B solo por alguna noción de "composición". En lugar de considerar si "a" es importante para el código usando una instancia de clase B. Si el código que usa B necesita llegar a "a", entonces debe haber una forma (método) en B para acceder a él. En su ejemplo, "a" es privado, por lo que su existencia y uso en B está completamente oculto para el código que usa la clase B. Esto generalmente es algo bueno. Más: http://en.wikipedia.org/wiki/Information_hiding http://en.wikipedia.org/wiki/Object_composition – rickmode

+0

Gracias, comencé un hilo diferente si devolvía una referencia a un miembro privado en la composición rompe OOP . En mi caso, B tiene que tener A y, sin embargo, el usuario necesita establecer algunos propertoes de A que requieran una forma de llegar a A. No quiero usar delegación, lo que me obligaría a exponer los métodos en B para cada método. en un. –

Cuestiones relacionadas