7
votes

Comment faire cela sans héritage multiple

J'ai un groupe de classes qui prolongent une seule classe abstraite. Un sous-ensemble de ces classes a besoin d'une implémentation identique de l'une des méthodes, un autre sous-ensemble des classes nécessite une autre mise en œuvre de la méthode et un troisième sous-ensemble nécessite une autre. Dans tout ce qu'il y a environ dix classes d'enfants, mais seulement trois mises en œuvre possibles de l'une des méthodes. (Il existe de nombreuses autres méthodes que les classes mettent en œuvre qui n'ont rien de commun.)

J'essaie de comprendre le meilleur moyen d'accomplir cela. Je pense que ce que j'aurais fait en C ++ est multiple héritage: créer des classes de trois qui implémentent cette méthode, puis les enfants hériter de l'une de ces trois classes appropriées. P>

y a-t-il une meilleure pratique pour faire Ceci en Java? P>

Je considérais une couche intermédiaire de trois classes abstraites, entre la principale classe abstraite et les enfants. Chacun des trois héritage de la classe abstrait principale et la mise en œuvre de la méthode en question. Ensuite, les enfants héritent de ces trois. Mais ce que je n'aime pas à propos de cela, c'est si une autre méthode vient avec un comportement similaire «regroupant», et il ne correspond pas aux trois classes «de niveau moyen»? Cela deviendrait laid p>

est l'une de cela en faisant de sens? J'écris à la hâte ... p>

Edit: B> Donc, 24 heures après ma question, j'ai reçu environ une demi-douzaine de modèles pour enquêter. Je ne suis pas encore sûr qu'ils soient tous des noms de modèle de conception officiels. Mais je vais regarder dans chacun puis rapporter (et choisir une réponse comme correcte). Les Pattens suggèrent jusqu'à présent: P>

* Delegation

* Bridge

* Strategy

* Composition

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


0 commentaires

5 Réponses :


3
votes

Si vous insistez sur la résolution de l'héritage, le modèle de pont de Le livre Gof pourrait aider ici (il peut ou non être un ajustement parfait, en fonction de laquelle les préoccupations de domaine provoquent la séparation en trois implémentations). Personnellement, je suis susceptible de simplement mettre les trois mises en œuvre de la méthode dans une classe d'assistance et transmettre les appels de méthode des classes (ce que JB NIZET se réfère correctement à la délégation).


2 commentaires

Merci pour le lien que je vais lire et revenir avec mes questions. Voulez-vous toujours écouter? Je suis nouveau ici. Les commentaires ont-ils affiché des réponses causant une sorte d'alerte à envoyer au répondeur?


Les commentaires sur les réponses déclenchent une petite notification, mais si vous avez des questions ultérieures, c'est plus dans l'esprit du site Web pour les poster comme neufs (lors de la vérification des doublons) au lieu de demander des réponses de suivi au plus ancien. Meta-Discussion telle que celle-ci a son propre sous-site et est fronçonné ici.



6
votes

Utilisez la délégation plutôt que sur l'héritage. Demandez à toutes les classes d'un même groupe déléguez-vous à un objet d'assistance commune pour mettre en œuvre leur méthode.


6 commentaires

Je pense que les modèles de pont et de stratégie évoluent également à la délégation. Lequel des motifs serait le mieux à votre avis? Ou devrions-nous faire sans les motifs ici (dans la mesure où une classe d'assistance n'est pas un modèle tout seul)? Je pense que l'asserfice est maintenant laissé avec plusieurs réponses, qui ne sont pas fausses par eux-mêmes ...


Le modèle de stratégie est celui qui semble le plus approprié, à l'exception du modèle de stratégie consiste à injecter une stratégie dans une classe. Dans ce cas, je ne pense pas que les classes doivent être configurables de l'extérieur. Une méthode doit simplement être externalisée à partir de la classe. Tout ne doit pas avoir de nom de motif et une délégation simple pourrait être suffisante ici.


D'accord. Les motifs sont gentils, mais ils ne doivent pas être utilisés dans des endroits où ils ne sont pas entièrement appropriés.


Merci JB. Je pense que je comprends ce que vous suggérez. Mais je veux être sûr. Par "délégué", vous voulez dire que la méthode de la classe enfant fait un appel explicite à la méthode de l'objet Helper? La "délégation" est-elle un nom de modèle de conception "officiel"? (Et qui maintient le registre des noms de modèle de conception officiels?)


Oh, attends une seconde! J'ai oublié de mentionner que j'ai besoin d'accéder à la quasi-totalité des membres privés de l'instance (plus d'une douzaine de fonctions et de variables). Donc, dans un tel motif, avec un tel exigence, l'enfant passe-t-il "cette" référence à la méthode déléguée?


Oui, ou il passe un objet personnalisé contenant uniquement les informations nécessaires



1
votes

La solution d'incendie rapide facile sans utiliser d'héritage serait de résumer les 3 "méthodes courantes" à ailleurs, puis répétez l'appel de la méthode.

Si vous voulez le faire de manière agréable OO, consultez le motif de décorateur qui pourrait bien aider ici - Créez vos 3 classes standard qui implémentent vos trois méthodes choisis, puis "les décorer" avec les autres classes .


0 commentaires

1
votes

Premièrement, envisagez de remplacer la classe abstraite avec une interface. Je ne sais pas si c'est possible Dans votre cas.

Deuxièmement, vous pouvez déléguer la fonctionnalité de votre méthode de «regroupement» à une autre classe (implémentateur). Créez 3 classes différentes avec implémentation de la méthode (ou seulement 3 méthodes différentes dans une classe) et appelez-les des classes d'enfants au besoin.

Donc, la méthode "regroupement" sera définie dans chaque classe enfant, mais il suffira d'appeler explicitement l'un des 3 implémentateurs possibles.


0 commentaires

7
votes

En fait, je sens un modèle de stratégie ici.

Vous pourriez avoir cette méthode dans la classe de base déléguée à une stratégie qui est transmise à la construction. Les sous-classes laissent juste passer l'un d'un ensemble de stratégies dans le cadre de leur construction. Les stratégies elles-mêmes pourraient être mises à la disposition de l'extérieur de la classe, soit à l'intérieur de la classe privée. Cela peut se retrouver avec moins de cours dans votre hiérarchie.

Cela étant dit, il y a des odeurs supplémentaires ici, même avec ma solution proposée. Vous voudrez peut-être réfléchir à un niveau supérieur avec des interfaces (comme mentionné par d'autres solutions) et une composition uniquement sans héritage. Au fil du temps, je suis arrivé à la conclusion que l'héritage n'est pas mon ami. De nos jours, j'évite le cas possible.


6 commentaires

Une stratégie ne doit pas nécessairement s'appliquer à une méthode. Je peux avoir une stratégie qui implémente plusieurs méthodes (si elles sont du tout regroupées de cette façon). Je peux également avoir plusieurs interfaces de stratégie et implémentations pour chacun, puis la combinant si nécessaire à la construction. Juste une pensée. Ne doit pas nécessairement être la meilleure réponse. EDIT: C'était une réponse à un commentaire qui a été supprimé pendant j'ai tapé. :)


J'aime tellement votre réponse que j'ai retiré le mien. Le modèle de stratégie peut également être utilisé une seconde fois si une autre des méthodes doit également être partagée entre les classes.


Désolé, j'ai enlevé le commentaire ... c'était mal et j'ai tellement ma réponse. Mais comme vous pouvez le voir de mon plus récent commentaire ci-dessus, je suis tout à fait d'accord avec vous.


Ah, se demandait ce qui s'est passé là-bas. Merci pour la clarification (et le support!) TOTO2.


Pour le modèle de stratégie, je fais quelque chose comme myx x = nouveau myxchild (nouveau mystrategy ()); Où mystrategy implémente la méthode en question? Une autre question: ai-je raison de penser qu'avec la "composition", les fonctions sont mises en œuvre par des classes variables des membres et n'ont donc pas accès à des membres privés et protégés de la classe enfant?


Les membres protégés sont accessibles à toutes les classes du même paquet, c'est donc un moyen de résoudre que, bien qu'il vaut mieux ne pas distribuer trop d'accès direct aux membres, ce qui peut facilement entraîner une faible encapsulation. Les membres privés et protégés peuvent être consultés par une classe interne (c'est-à-dire définir une classe sans la première classe). Les méthodes privées ne peuvent être accédées par aucune autre classe (sauf lorsque "Tricher" par réflexion, une instrumentation bytecode et d'autres fonctionnalités avancées non destinées à une utilisation normale de la programmation).