J'ai quelques malentendus au sujet des conditions des délégués et des rappels en Java.
class MyDriver {
public static void main(String[] argv){
MyObject myObj = new MyObject();
// definition of HelpCallback omitted for brevity
myObj.getHelp(new HelpCallback () {
@Override
public void call(int result) {
System.out.println("Help Callback: "+result);
}
});
}
}
class MyObject {
public void getHelp(HelpCallback callback){
//do something
callback.call(OK);
}
}
Est-ce rappel ou délégué ( Les délégués et les rappels sont-ils identiques ou similaires? )?
Comment mettre en œuvre alors un autre?
Ceci est un rappel. _ { Selon Wikipedia }:
En programmation informatique, un rappel est une référence à un morceau de code exécutable qui est passé comme argument à un autre code.
Alors regardons le code exécutable:
public void getHelp(HelpCallback callback){
//do something
callback.call(OK);
}
Ici, l'argument callback
est une référence à un objet de type HelpCallback
. Puisque cette référence est transmise en tant qu'argument, il s'agit d'un rappel.
La délégation est effectuée en interne par l'objet, indépendamment de la façon dont la méthode est appelée. Si, par exemple, la variable callback
n'était pas un argument, mais plutôt une variable d'instance:
class MyDriver {
public static void main(String[] argv){
// definition of HelpStrategy omitted for brevity
MyObject myObj = new MyObject(new HelpStrategy() {
@Override
public void getHelp() {
System.out.println("Getting help!");
}
});
myObj.getHelp();
}
}
class MyObject {
private final HelpStrategy helpStrategy;
public MyObject(HelpStrategy helpStrategy) {
this.helpStrategy = helpStrategy;
}
public void getHelp(){
helpStrategy.getHelp();
}
}
... alors ce serait une délégation.
Ici, MyObject
utilise le modèle de stratégie . Il y a deux choses à noter:
getHelp()
n'implique pas de passer une référence au code exécutable. c'est-à-dire qu'il ne s'agit pas d'un rappel.MyObject.getHelp()
appelle helpStrategy.getHelp()
n'apparaît pas clairement dans l'interface publique de l'objet MyObject
ni dans l'invocation getHelp()
. Ce type de masquage d'informations est quelque peu caractéristique de la délégation.Il convient également de noter l'absence de section // do something
dans la méthode getHelp()
. Lors de l'utilisation d'un rappel, le rappel n'a aucune incidence sur le comportement de l'objet: il avertit simplement l'appelant d'une manière ou d'une autre. C'est pourquoi une section // do something
était nécessaire. Cependant, lors de l’utilisation de la délégation, le comportement réel de la méthode dépend du délégué; il est donc possible que nous ayons besoin des deux car ils ont des objectifs distincts:
public void getHelp(HelpCallback callback){
helpStrategy.getHelp(); // perform logic / behavior; "do something" as some might say
if(callback != null) {
callback.call(); // invoke the callback, to notify the caller of something
}
}
Je dirais que "callback" est un nom pour un modèle générique dans lequel vous fournissez au module que vous appelez un moyen permettant à ce module d'appeler votre code. Un délégué C # ou un objet délégué ObjC (ces deux objets sont des bêtes totalement différentes) ou une classe Java qui implémente l'interface de rappel est une manière différente, spécifique à la plate-forme, d'implémenter le modèle de rappel. (Ils peuvent aussi être eux-mêmes considérés comme des motifs.) Les autres langues ont des façons plus ou moins subtiles de le faire.
Le concept ci-dessus de "délégué" est également similaire au modèle de stratégie, où le délégué peut être considéré comme un seul. De même, un visiteur est également un type de rappel. (Un visiteur est également une stratégie de traitement de chaque élément visité.)
Tout cela, c’est utiliser des définitions qui me sont intuitives et qui pourraient ne pas l'être pour quelqu'un d'autre, car ni "rappel" ni "délégué" ne sont des termes formels et il est peu logique de les discuter sans faire référence à une définition antérieure valable le contexte. Par conséquent, il est peu logique de demander quelle est la définition, étant donné qu’à ma connaissance, il n’existe pas de définition faisant autorité. À savoir, le fait que d'autres réponses à cette question sont susceptibles de dire quelque chose de complètement différent.
Ma recommandation serait de vous concentrer sur les mérites de votre conception - si elle répond à vos besoins, n'introduit pas de couplage étroit, etc. - plutôt que sur une minutie de la sémantique. Lorsque deux modèles de conception semblent similaires, ils peuvent probablement être utilisés pour atteindre des objectifs similaires.
Vous voulez obtenir une communication bidirectionnelle entre l'appelant initial et un service, tout en évitant que le service dépende du client. Le modèle que vous utilisez pour atteindre cet objectif dépend souvent des restrictions de votre langue. Vous utilisez des pointeurs de fonction, des fermetures ou, si vous n'en avez aucune, des objets de rappel (pouvant également être considérés comme des fermetures).
Et puis, il y a souvent beaucoup de noms différents pour un motif identique ou très similaire.