2012-06-19 4 views
4

Je suis encore un peu néophyte dans le développement de programmation et j'ai du mal à faire un design propre. Spécifiquement, j'ai un scénario comme ci-dessous:Aide à la conception Java. Héritage et code de partage

J'ai 4 classes, chacune avec la fonctionnalité commune. Appelons ces méthodes A, B, C, etc.

classe: Compte; méthodes: A, B, C, G, H, I, S1, S2, S3
classe: Dossier; méthodes: A, B, C, D, E, S1, S2, S3
classe: Groupe; méthodes: A, B, C, D, E, F, S1, S2, S3
classe: Rôle; méthodes: A, B, C, D, E, F, S1, S2, S3

Les méthodes spécifiées ci-dessus sont abstraites. Comme dans il pourrait y avoir un FooAccount et un BarAccount qui implémentent la méthode A différemment. Cependant FooAccount et FooGroup ont la même méthode A (puisqu'ils sont de la même implémentation, Foo). Pas trop mal, sauf qu'il y a aussi des méthodes S1, S2 et S3 qui sont implémentées à l'identique même entre Foo et Bar pour que FooAccount et BarAccount aient des méthodes identiques S1, S2 et S3.

Actuellement ma conception est assez laid:

Interface Object1: déclare A, B, C
Object2 étend Object1 Interface : déclare D, E
Interface Object3 étend Object2: déclare F
Interface Le compte s'étend Objet1: déclare G, H, I
interface Dossier exte nds Object2;
Le groupe d'interface étend Object3;
interface Le rôle s'étend Object3;
Classe d'assistance: définit S1, S2, S3

Je sais que plusieurs héritages sont interdites pour une bonne raison, mais si on me permettait de le faire pour que je puisse mettre les méthodes S1, S2 et S3 dans Object1 et transforme toutes les interfaces en abstracts. Alors FooAccount pourrait étendre à la fois le compte et FooObject1.

Quelqu'un peut-il me donner quelques conseils pour quelle structure pourrait être mieux? Devrais-je simplement mettre tout A, B, C, etc. dans une classe Util (par exemple FooUtil et BarUtil)?

Répondre

2

Vous devez regrouper les méthodes dans les interfaces en fonction du rôle et non de l'occurrence.Donc, en supposant A, B, C appartiennent à un rôle, D et E appartiennent à une autre et F est dans son propre

interface Role1 - A, B, C 
interface Role2 - D, E 
interface Role3 - F 
interface Account extends Role1 
interface Folder extends Role1, Role2 
interface Group extends Role1, Role2, Role3 

Si vous avez mise en œuvre commune des méthodes, vous pouvez les déplacer vers une classe de base abstraite qui fournit mises en œuvre par défaut

abstract class Helper - S1, S2, S3 

alors vous pouvez déclarer vos classes concrètes

class FooAccount extends Helper implements Account 

Vous pouvez également envisager d'utiliser les médicaments génériques si vous pouvez extraire le comportement commun à Foo et Bar et ont Account être une classe générique (en Foo et Bar) au lieu d'une interface

+0

Merci pour la réponse, mais à moins que je ne me trompe, puisque Account/Group ne sont que des interfaces, je devrais écrire la méthode A explicitement dans chacune des classes. J'essaie de réduire autant que possible le code en double ... – kennyg

+0

@kennyg - Si vous avez une implémentation commune des méthodes, vous pouvez les utiliser dans une classe abstraite dont vous héritez (voir l'exemple avec 'Helper' - vous pouvez certainement créer plus de telles classes de base abstraites auxiliaires pour fournir une implémentation commune de 'A',' B' et 'C'). Mais comme dans votre conception, le partage tourne autour de 'Foo' et' Bar' (toutes les classes 'Foo *' ont le même 'A' et toutes les classes' Bar * 'ont le même' A' (qui est différent de 'Foo ' * 'contreparties)), [suite] – Attila

+0

[cont.] vous devez implémenter' A' dans une classe 'Foo' (aussi' Bar') que vous passez dans les implémentations 'Account', etc. appelle la méthode 'A' de l'objet transmis. De cette façon, l'implémentation est suffisamment générique pour que vous puissiez facilement créer une classe 'FooBar', tout en capturant le code partagé correctement. – Attila

0

Ne comptez pas sur l'héritage en tant que mécanisme réduire le code répétitif. Au lieu de cela, trouver un moyen de séparer les responsabilités en classes distinctes.

FooAccount et FooGroup ont la même méthode A

Cela me dit que la mise en œuvre de la méthode A appartient à sa propre classe (FooA). S'il est vraiment logique pour Account et Group pour exposer la méthode A, alors la mise en œuvre de FooAccount.A et FooGroup.A devrait simplement être pass-through à FooA.A.

+0

Pourriez-vous entrer plus de détails sur le transfert? Voulez-vous dire que FooAccount.A appelle simplement FooA.A? – kennyg

+0

@kennyg: Exactement. Un simple appel de méthode ne viole pas le principe DRY à mon avis. La vraie logique que vous voulez éviter de dupliquer réside dans FooA.A, donc si vos autres classes ont besoin d'implémenter cette méthode pour le bien de votre API, ils peuvent juste déléguer la responsabilité à la classe FooA. – StriplingWarrior