Intent

  • Componer objetos en estructuras de árbol para representar jerarquías completas. Composite permite a los clientes tratar objetos individuales y composiciones de objetos de manera uniforme.
  • Composición recursiva
  • «Los directorios contienen entradas, cada una de las cuales podría ser un directorio»
  • 1-a-muchos «tiene un» hasta la jerarquía «es un»

Problema

La aplicación necesita manipular una colección jerárquica de objetos «primitivos» y «compuestos». El procesamiento de un objeto primitivo se maneja de una manera, y el procesamiento de un objeto compuesto se maneja de manera diferente.Tener que consultar el «tipo» de cada objeto antes de intentar procesarlo no es deseable.

Discusión

Defina una clase base abstracta (Componente) que especifique el comportamiento que debe ejercerse de manera uniforme en todos los objetos primitivos y compuestos. Subclasificar las clases Primitive y Composite a partir de la clase Component. Cada objeto Composite se «acopla» sólo al tipo abstracto Component mientras gestiona sus «hijos».

Use este patrón siempre que tenga «composites que contengan componentes, cada uno de los cuales podría ser un composite».

Los métodos de gestión de los hijos deberían definirse normalmente en la clase Composite. Lamentablemente, el deseo de tratar de manera uniforme a los Primitives y Composites requiere que los métodos se trasladen a la clase abstracta Component. Véase la sección «Opiniones» más adelante para una discusión de las cuestiones de «seguridad» frente a las de «transparencia».

Estructura

Composites que contienen Componentes, cada uno de los cuales podría ser unComposite.

Menús que contienen elementos de menú, cada uno de los cuales podría ser un menú.

Administradores de diseño GUI de fila-columna que contienen widgets, cada uno de los cuales podría ser un administrador de diseño GUI de fila-columna.

Directorios que contienen archivos, cada uno de los cuales podría ser un directorio.

Contenedores que contienen elementos, cada uno de los cuales podría ser un contenedor.

Ejemplo

El Composite compone objetos en estructuras de árbol y permite al cliente tratar objetos individuales y composiciones de manera uniforme. Aunque el ejemplo es abstracto, las expresiones aritméticas son Composites. Una expresión aritmética consta de un operando, un operador (+ – * /), y otro operando. El operando puede ser un número u otra expresión aritmética. Así, 2 + 3 y (2 + 3) + (4 * 6) son ambas expresiones válidas.

Lista de comprobación

  1. Asegúrese de que su problema trata de representar relaciones jerárquicas de «parte entera».
  2. Considere la heurística, «Contenedores que contienen containees, cada uno de los cuales podría ser un contenedor». Por ejemplo, «Ensamblajes que contienen componentes, cada uno de los cuales podría ser un ensamblaje». Divida sus conceptos de dominio en clases contenedoras y clases contenedoras.
  3. Cree una interfaz de «mínimo común denominador» que haga que sus contenedores y contenedores sean intercambiables. Debe especificar el comportamiento que debe ejercerse de manera uniforme en todos los objetos contenedores.
  4. Todas las clases contenedoras y contenedoras declaran una relación «es un» a la interfaz.
  5. Todas las clases contenedoras declaran una relación «tiene un» a la interfaz.
  6. Las clases contenedoras aprovechan el polimorfismo para delegar en sus objetos contenedores.
  7. Los métodos de gestión de los hijos deberían definirse normalmente en la clase Composite. Desafortunadamente, el deseo de tratar los objetos Leaf y Composite de manera uniforme puede requerir que los métodos sean promovidos a la clase abstracta Component. Ver el Gang ofFour para una discusión de estos «seguridad» versus «transparencia» trade-offs.

Reglas del pulgar

  • Composite y Decorator tienen diagramas de estructura similar, lo que refleja el hecho de que ambos se basan en la composición recursiva para organizar un open-endednumber de objetos.
  • Composite puede ser atravesado con Iterator. El visitante puede aplicar una operación sobre un Composite. Composite puede utilizar Chain ofResponsibility para que los componentes accedan a las propiedades globales a través de su padre. También puede utilizar Decorator para anular estas propiedades en las partes de la composición. Podría utilizar Observer para vincular una estructura de objetos a otra y State para permitir que un componente cambie su comportamiento a medida que cambia su estado.
  • Composite puede permitirte componer un Mediator a partir de piezas más pequeñas a través de la composición recursiva.
  • Decorator está diseñado para permitirte añadir responsabilidades a los objetos sin subclases. Composite no se centra en el embellecimiento sino en la representación. En consecuencia, Composite y Decorator se utilizan a menudo en concierto.
  • Flyweight se combina a menudo con Composite para implementar leafnodes compartidos.

Opiniones

El objetivo del patrón Composite es que el Composite puede ser creado atómicamente, al igual que una hoja. Si usted quiere proporcionar un protocoloIterator, bien, pero creo que es fuera de la patternitself. En el corazón de este patrón está la capacidad de un cliente para realizar operaciones en un objeto sin necesidad de saber que hay muchos objetos en su interior.

Poder tratar una colección heterogénea de objetos de forma atómica (o transparente) requiere que la interfaz de «gestión de hijos» se defina en la raíz de la jerarquía de clases Composite (la clase abstractComponent). Sin embargo, esta elección le cuesta seguridad, porque los clientes pueden intentar hacer cosas sin sentido como añadir y eliminar objetos de los objetos hoja. Por otro lado, si se «diseña para la seguridad», la interfaz de gestión de los niños se declara en la clase Composite, y se pierde la transparencia porque las hojas y los Composites tienen ahora diferentes interfaces.

Las implementaciones demalltalk del patrón Composite no suelen tener la interfaz de gestión de los componentes en la interfaz Component, sino en la interfaz Composite. Las implementaciones de C++ tienden a ponerla en la interfaz Componente. Se trata de un hecho muy interesante, sobre el que reflexiono a menudo. Puedo ofrecer teorías para explicarlo, pero nadie sabe con certeza por qué es cierto.

Mis clases de Componentes no saben que los Composites existen. No proporcionan ninguna ayuda para navegar por los Composites, ni ninguna ayuda para alterar los contenidos de un Composite. Esto es porque me gustaría que la clase base (y todos sus derivados) sean reutilizables en contextos que no requieren Composites. Cuando se da un puntero de clase base, si es absolutamente necesario saber si es o no un Composite, utilizaré dynamic_cast para averiguarlo. En los casos en que dynamic_cast es demasiado caro, voy a utilizar un Visitante.

Queja común: «si empujo la interfaz Composite hacia abajo en la claseComposite, ¿cómo voy a enumerar (es decir, atravesar) una complexstructure?» Mi respuesta es que cuando tengo comportamientos que se aplican a jerarquías como la presentada en el patrón Composite, normalmente utilizo Visitor, por lo que la enumeración no es un problema – el Visitante sabe en cada caso, exactamente con qué tipo de objeto está tratando. El Visitante no necesita que cada objeto proporcione una interfaz de enumeración.

Composite no te obliga a tratar todos los Componentes como Composites. Simplemente te dice que pongas todas las operaciones que quieras tratar «uniformemente» en la clase Componente. Si las operaciones de añadir, eliminar y otras similares no pueden, o no deben, ser tratadas uniformemente, entonces no las ponga en la clase base Componente. Recuerde, por cierto, que el diagrama de estructura de cada patrón no define el patrón; simplemente representa lo que en nuestra experiencia es una realización común del mismo. El hecho de que el diagrama de estructura de Composite muestre operaciones de gestión de hijos en la clase base Component no significa que todas las implementaciones del patrón deban hacer lo mismo.

¡Apoye nuestro sitio web gratuito y adquiera el libro electrónico!

  • 22 patrones de diseño y 8 principios explicados en profundidad
  • 406 páginas bien estructuradas, fáciles de leer y sin jerga
  • 228 ilustraciones y diagramas claros y útiles
  • Un archivo con ejemplos de código en 4 idiomas
  • Todos los dispositivos compatibles: Formatos EPUB/MOBI/PDF

Más información…

Deja una respuesta

Tu dirección de correo electrónico no será publicada.