6
votes

Comment ajouter le contrôle sur l'invoquant des méthodes dans des sous-classes existantes sans modifier les sous-classes?

J'ai quelques basoclass avec une méthode void dosshaniquing () .

Il existe différentes façons de Fosomething et ils sont mis en œuvre par Sous-classe1 , Sous-classe2 et Sous-Class3 .

Maintenant, je veux ajouter un Boolean Active Propriété au basoclass de sorte que lorsque dosomething est appelé sur une instance qui reviendrait sans rien faire.

Je sais que je peux coder le Basoclass pour avoir dosomething () qui ressemble à quelque chose comme: xxx

puis @Override réellement () Au lieu de @override dosomething () dans les sous-classes. Mais il se sent mal ... En ce sens qu'il a déjà été convenu que les sous-classes devraient fournir une implémentation de dossomique () et ils ne sont pas au courant de réellement () .

i peut aussi avoir chaque sous-classe ajouter un si (! this.getactive ()) retourner; au début de sa mise en œuvre de DOSMATHIAT () Mais cela semble aussi faux que sa fonctionnalité commune que je préférerais rester communes.

Quelle est la façon commune / la meilleure pratique de faire cela? Peut-il être fait sans changer les sous-classes?

Mise à jour

L'objectif du Q n'est pas sur la bonne façon de concevoir une telle fonctionnalité (qui est assez facile), mais sur la manière dont cette fonctionnalité peut être ajoutée à un scénario existant sans rien ne rien briser.

actif serait vrai, mais il est souhaitable que sur Toute instance de ladite sous-catégorie si quelqu'un appelle setactive (false) alors il deviendra des appels inactifs et consécutifs vers .Dosomething () ne fera rien ...


6 commentaires

Faites réellement réellement () abstrait et protégé dans votre classe de base. Demandez-le dans les cours d'enfant. Dosomething () devrait éventuellement être final . En Java, suivez les conventions de nommage Java.


L'intention est donc d'avoir cette fonctionnalité de définition du drapeau actif dans toutes les classes - également dans les dérivés? Si tel est le cas, la solution suggérée par Sotirios Delimanolis semble la plus appropriée. Sinon, en fonction de l'intention réelle, vous pouvez envisager une classe "wrapper" qui déléguette l'appel uniquement lorsque le drapeau est défini - comme si (actif) déléguée.dosomething ()


Changé le boîtier de mes méthodes (désolé pour cela). Travailler avec abstraite protégé réellement_dosomething () est une bonne idée si c'est la façon dont les choses sont prévues pour commencer ... Mon Q consiste à changer une situation existante. (Peut-être que la réponse reste la même) ... N'y a-t-il aucune façon raisonnable de faire cela 1) sans introduire de changer les classes? 2) Sans introduire une méthode nouvelle et différente? Que feriez-vous si vous aviez des dizaines ou des centaines de sous-classes pour la baseClass? Serez-vous au HVAE pour tout changer? et tout le code qui les utilise déjà?


@EPELEG À cause du polymorphisme, vous ne pouvez pas forcer un appel sur un objet de sous-classe pour passer d'abord la mise en œuvre du parent. Il y aura des changements considérables à faire. Vous pouvez les minimiser en refactorant d'abord le nom de la méthode de dosomething () à réellement_dosomething () puis changez simplement la classe mère en ajoutant un nouveau DOSMATHIAT () < / code> méthode.


@Alex, je ne suis pas assez familier avec la programmation orientée forme, et je ne sais pas que je comprends comment utiliser votre commentaire.


J'ai posté une réponse (longue) décrivant en profondeur comment vous pouvez ajouter la fonctionnalité sans rien casser.


3 Réponses :


1
votes

Je me tromperai peut-être, mais peut-être que vous recherchez la méthode de modèle modèle de conception. Pls voir: http://www.oodesign.com/template-method-pattern.html

ou juste chercher le modèle avec Google, il y a de très beaux sites à ce sujet. J'espère pouvoir aider.


2 commentaires

Cela n'aide pas non plus parce que cela nécessite à nouveau que je sache à l'avance que je veux avoir cette fonctionnalité ...


Désolé, je n'ai pas vu la section de mise à jour de votre question. Avec cela, je dirais que le motif de décorateur (Prinilpe ouvert) autour de votre classe de base où vous implémentez cette nouvelle fonctionnalité car Marco13 mentionné. Mais bien sûr, les plus agréables soultions peuvent être venues.



3
votes

Vous voulez utiliser @ArtonD code> conseils de AspectJ et faire quelque chose comme ceci:

BEFORE ======
SubClass1: doSomething() called.
SubClass2: doSomething() called.
SubClass3: doSomething() called.

AFTER ======
Blocking instance<1> method: my.first.spring.aop.aspectj.SubClassN#doSomething([]) !!
Blocking instance<2> method: my.first.spring.aop.aspectj.SubClassN#doSomething([]) !!
Blocking instance<3> method: my.first.spring.aop.aspectj.SubClassN#doSomething([]) !!


3 commentaires

Bonjour Alex, je tiens tout d'abord à vous remercier pour une réponse très écrite. C'était très intéressant de lire et peut probablement aider les autres. Malheureusement, je ne peux pas l'utiliser comme j'utilise Java 6 et n'utilise pas le printemps. Et même si ce n'était pas le cas, c'est un peu trop mort pour moi pour que cela puisse ajouter cela. Cela dit, j'accepterai toujours votre réponse en raison de sa haute qualité et j'ajouterai une autre réponse décrivant ce que j'ai fini par faire moi-même.


@EPELEG La solution est compatible avec Java 6. Il suffit de changer maven.compiler.source et maven.compiler.target à 1.6. Il est possible d'utiliser AspectJ sans printemps. Cela entraînera plus de travail pour la mise en place de tout.


@EPELEG Voici le code source complet comme une commodité: FileDropper.com/adviceAroundSample



1
votes

Alors, ce que je ferais, c'est ce que je ferais, c'est le suivant:

Ajouter à la classe de base Une nouvelle signature pour DOSMATHIGHT CODE> P>

@Override
public boolean someThingCanBeDone() {
  return base.someThingCanBeDone() && someConditionLocalToTheSubclass;
}


0 commentaires