Est-il acceptable d'avoir des «points d'ancrage» d'instanciation d'objets dans les classes de base?

StackOverflow https://stackoverflow.com/questions/148056

  •  02-07-2019
  •  | 
  •  

Question

J'ai créé ma propre implémentation de Tree pour pour diverses raisons et j'ai mis au point deux classes, une classe de base qui est un nœud d’arbre générique plein de logique et une autre classe qui étend celle qui est plus spécialisée.

Dans ma classe de base, certaines méthodes impliquent l'instanciation de nouveaux nœuds d'arborescence (par exemple, l'ajout d'enfants). Ces instants sont une logique interne (dans une boucle imbriquée, par exemple), ce qui rend la logique difficile à séparer de l’instantation.

Donc, si je ne remplace pas ces instants dans la classe spécifique, le type de nœud incorrect sera créé. Cependant, je ne veux pas remplacer ces méthodes car elles contenaient également une logique partagée qui ne devrait pas être dupliquée!

Le problème peut se résumer à ceci:

public class Foo {
    public String value() { return "foo"; }

    public Foo doStuff() {
        // Logic logic logic..
        return new Foo();
    }
}

class Bar extends Foo {
    public String value() { return "bar"; } 
}

new Bar().doStuff().value(); // returns 'foo', we want 'bar'

La première chose qui me trottait dans la tête aurait un crochet de création que les classes d'extension pourraient surcharger:

public Foo createFooHook(/* required parameters */) {
  return new Foo();
}

Maintenant. bien que ce fût une bonne idée, il y a une puanteur qui se dégage de ce code, quelque chose de terrible. Il y a quelque chose de très ... faux à ce sujet.

C’est comme cuisiner nu: c’est dangereux et inutile .

Alors, comment feriez-vous face à cette situation?

Était-ce utile?

La solution

Donc, après avoir reçu ma copie de Design Patterns et l'avoir ouverte pendant Je suis presque sûr que c'est la première fois que je découvre ce que je veux.

C'est ce qu'on appelle la la méthode d'usine et la plupart du temps, elle convient parfaitement. C'est toujours un peu moche parce que ma super classe ( Foo dans l'exemple ci-dessus) n'est pas abstraite, ce qui signifie que les sous-classes ne sont pas obligées d'implémenter le hook.

Cela peut être corrigé avec une refactorisation cependant, et je finirai avec quelque chose à l'effet de:

abstract class AbstractFoo {
    public String value() { return "Foo"; }

    public AbstractFoo doStuff() {
        // Logic logic logic
        return hook();
    }

    protected abstract AbstractFoo hook();
}

class Foo extends AbstractFoo {
    protected AbstractFoo hook() { return new Foo(); }
}

class Bar extends AbstractFoo {
    public String value() { return "Bar"; }

    protected AbstractFoo hook() { return new Bar(); }
}

new Bar().doStuff().value(); // Returns 'Bar'!

Autres conseils

En plus du motif Factory, je jetterais un coup d'œil au motif Composite - il a tendance à bien se prêter au travail avec une Factory dans des situations basées sur des arbres.

modèle de conception composite

Je ne pense pas qu'il existe une meilleure approche. Faites juste attention à ne pas appeler ces hooks depuis le constructeur.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top