Implémenter une chaîne de travail avec un modèle de méthode de modèle ?
-
09-12-2019 - |
Question
J'ai une hiérarchie de worker
classes, qui effectuent toutes une sorte de traitement sur une pièce.L'idée est que chaque travailleur effectue un pré-traitement, pousse la pièce vers la sous-classe, puis effectue un post-traitement :
public void process(Workpiece wp) {
doPreprocessing(wp);
sub.process(wp); // this obviously doesn't work
doPostProcessing(wp);
}
En ce moment, je résous ce problème en déclarant de nouvelles méthodes abstraites :
public final void process(Workpiece wp) {
doPreprocessing(wp);
subProcess(wp); // this obviously doesn't work
doPostProcessing(wp);
}
protected abstract void subProcess(Workpiece wp);
ce qui présente l'inconvénient évident que pour chaque niveau hiérarchique, il existe une nouvelle méthode supplémentaire.
Je voudrais garantir que toutes les méthodes de pré- et post-traitement sont exécutées même avec de nouveaux travailleurs implémentés par l'utilisateur, qui ne sont pas sous mon contrôle.
Comment feriez-vous cela?
La solution
En suivant le modèle de méthode modèle, vous feriez cela en concevant votre classe de telle sorte que le doPreProcessing
et doPostProcessing
les méthodes sont remplacées dans les sous-classes.Je suppose que vous ne voulez pas faire cela, car vous ne pouvez pas être sûr que les sous-classes appelleront super, et vous ne pouvez donc pas « garantir que toutes les méthodes de pré- et post-traitement sont exécutées même avec un nouvel utilisateur. -travailleurs mis en œuvre."
Au lieu d'utiliser l'héritage, vous pouvez essayer une conception qui enchaîne les objets de travail, comme ceci :
public abstract class Worker {
private Worker next;
protected Worker(Worker next) {
this.next = next;
}
public void process(Workpiece wp) {
preProcess(wp);
if (next != null)
next.process(wp);
postProcess(wp);
}
public abstract void preProcess(Workpiece wp);
public abstract void postProcess(Workpiece wp);
}
Vos classes et les classes implémentées par l'utilisateur, au lieu d'étendre le travailleur "suivant", créent le travailleur "suivant" dans leurs constructeurs :
public class MyWorker extends Worker {
public MyWorker() {
super(new MyOtherWorker());
}
public abstract void preProcess(Workpiece wp) {
// code
}
public abstract void postProcess(Workpiece wp) {
// code
}
}