2012-01-02 15 views
7

Tengo un grupo de clases que extienden una sola clase abstracta. Un subconjunto de estas clases necesita una implementación idéntica de uno de los métodos, otro subconjunto de las clases necesita otra implementación del método, y un tercer subconjunto requiere otro. En total hay alrededor de diez clases secundarias, pero solo tres posibles implementaciones de uno de los métodos. (Hay muchos otros métodos que implementan las clases que no tienen nada en común.)Cómo hacer esto sin herencia múltiple

Estoy tratando de encontrar la mejor manera de lograr esto. Creo que lo que habría hecho en C++ es herencia múltiple: crear tres clases que implementen solo este método, luego haga que los niños hereden de la apropiada de esas tres clases.

¿Existe una mejor práctica para hacer esto en Java?

Estaba considerando una capa intermedia de tres clases abstractas, entre la clase abstracta principal y los niños. Cada uno de los tres hereda de la clase abstracta principal e implementa el método en cuestión. Entonces los hijos heredan de estos tres. Pero lo que no me gusta de eso es ¿qué ocurre si otro método viene con un comportamiento similar de "agrupamiento" y no se corresponde con las tres clases de "nivel medio"? Eso se pondría feo

¿Tiene algo de sentido? Estoy escribiendo aprisa ...

EDIT: Entonces, 24 horas después de hacer mi pregunta, he recibido aproximadamente media docena de patrones para investigar. Todavía no estoy seguro de que sean nombres de patrones de diseño oficiales. Pero voy a analizar cada uno y luego informaré (y elegiré una respuesta como correcta). Los zuecos sugeridas hasta ahora:

* Delegation 

* Bridge 

* Strategy 

* Composition 

* Decorator (if I was choosing on name alone, I choose this one) 

que también tienen que añadir que el método que se está implementando necesita tener acceso a casi todos los miembros privados de la clase. Entonces eso tendrá un gran factor en mi elección.

Respuesta

3

Si insistes en resolverlo a través de la herencia, el bridge pattern del libro de GoF podría ayudar aquí (puede o no ser un ajuste perfecto, dependiendo de qué preocupaciones de dominio causen la separación en tres implementaciones). Personalmente, es probable que coloque las tres implementaciones de métodos en una clase auxiliar y reenvíe las llamadas a métodos de las clases (a lo que JB Nizet se refiere correctamente como delegación).

+0

Gracias por el enlace voy a leer y volver con mis preguntas. ¿Todavía estarás escuchando? Soy nuevo aqui. ¿Los comentarios publicados en las respuestas provocan que se envíe algún tipo de alerta al que responde? –

+0

Los comentarios a las respuestas activan una pequeña notificación, pero si tiene preguntas posteriores, es más conveniente que el sitio web las publique como nuevas (mientras busca los duplicados) en lugar de solicitar respuestas de seguimiento en la anterior. Meta-discussion como este tiene [su propio sitio secundario] (http://meta.stackoverflow.com/) y está mal visto aquí. – Barend

6

Usa la delegación en lugar de la herencia. Haga que todas las clases de un mismo grupo deleguen en un objeto auxiliar común para implementar su método.

+0

Creo que los patrones Puente y Estrategia también se reducen a delegación. ¿Cuál de los patrones sería el mejor en tu opinión? ¿O deberíamos prescindir de los patrones aquí (en la medida en que una clase auxiliar no es un patrón en sí mismo)? Creo que el asker ahora tiene múltiples respuestas, todas las cuales no están mal por sí mismas ... –

+0

El patrón de estrategia es el que parece ser el más apropiado, excepto que el patrón de estrategia consiste en inyectar una estrategia en una clase. En este caso, no creo que las clases tengan que ser configurables desde el exterior. Un método solo debe ser externalizado de la clase. Todo no debe tener un nombre de patrón, y la delegación simple podría ser suficiente aquí. –

+0

De acuerdo. Los patrones son agradables, pero no deben usarse en lugares donde no son * completamente * apropiados. –

1

La solución de disparo rápido y fácil sin usar herencia sería abstraer los 3 "métodos comunes" a otro lugar, y luego simplemente repetir la llamada al método.

Si desea hacerlo de una manera agradable OO, eche un vistazo al patrón de decorador que bien puede ayudar aquí - cree sus 3 clases estándar que implementan sus tres métodos elegidos y luego "decorarlos" con el otro clases

1

Primero, considere reemplazar la clase abstracta con una interfaz. No sé si es posible en su caso.

En segundo lugar, puede delegar la funcionalidad de su método de "agrupamiento" a otra clase (implementador). Cree 3 clases diferentes con la implementación del método (o solo 3 métodos diferentes en alguna clase) y llámelos de las clases secundarias según sea necesario.

Por lo tanto, el método de "agrupamiento" se definirá en cada clase secundaria pero llamará explícitamente a uno de los 3 posibles implementadores.

7

En realidad, huelo un patrón de estrategia aquí.

Puede tener ese método en la clase base delegada a una estrategia que se transfiere en la construcción. Las subclases simplemente pasan en cualquiera de un conjunto de estrategias como parte de su construcción. Las Estrategias mismas podrían estar disponibles ya sea fuera de la clase, o internamente como clases privadas. Esto puede terminar con menos clases en general en su jerarquía.

Dicho esto, hay olores adicionales aquí, incluso con mi solución propuesta. Es posible que desee pensar en un nivel superior con las interfaces (como se menciona en otras soluciones) y la composición solo sin herencia. Con el tiempo llegué a la conclusión de que la herencia NO es mi amiga. Hoy en día lo evito cuando sea posible.

+0

Una estrategia no tiene que aplicarse solo a 1 método. Puedo tener una estrategia que implemente múltiples métodos (si están agrupados de esa manera). También puedo tener múltiples interfaces de estrategia e implementaciones para cada una, y luego combinarlas según sea necesario en la construcción. Solo un pensamiento. No tiene que ser la mejor respuesta. EDITAR: Esta fue una respuesta a un comentario que se eliminó * mientras * escribí. :) – rfeak

+0

Me gusta tu respuesta tanto que eliminé la mía. El patrón de estrategia también se puede utilizar por segunda vez si también se debe compartir otro de los métodos entre las clases. – toto2

+0

Lo siento, eliminé el comentario ... estaba mal y también mi respuesta. Pero como puede ver en mi nuevo comentario anterior, estoy completamente de acuerdo con usted. – toto2