6 votes

Collection paresseuse en Java

Considérez un problème, dans lequel je développe une collection en forme d'arbre.

Une des fonctionnalités principales de ma collection est de suivre tous les éléments stockés un par un, puis d'appeler une fonction donnée pour chaque élément jusqu'à ce qu'un critère donné soit atteint (collection paresseuse).

Donc la fonction devrait avoir les signatures suivantes :

void Trace(function func, criteria crit)
{
    item i = firstItem();
    while (i != endItem())
    {
        i = nextItem();
        func(i);
        if (crit(i))
            return;
    }
}

en C++, les pointeurs de fonction peuvent être utilisés pour func et crit.
en C#, le mot-clé yield est exactement la solution à ce problème, je crois.

Comment puis-je obtenir la même chose en Java ?

2voto

Isaac Points 8187

En Java, vous passeriez des références à des objets de classes qui implémentent des fonctions applicables, ou utilisez plutôt Commons Collections :

Par exemple:

Closure c = new Closure() {
    public void execute(Object obj) {
        ...
    }
};

Predicate p = new Predicate() {
    public boolean evaluate(Object obj) {
        ...
    }
}

Trace(c, p);

2voto

Dancrumb Points 11918

Ce que vous recherchez ici, c'est le modèle de conception Strategy.

L'objectif de ce modèle est d'abstraire l'implémentation d'un algorithme dans un objet Strategy. Ici, vos algorithmes sont les fonctions func et crit que vous souhaitez passer en paramètre.

Donc, vous auriez une interface appelée quelque chose comme TraceStrategy. Vous passeriez ensuite des implémentations de cette interface dans votre collection. Votre code ressemblerait alors à quelque chose comme

void Trace(TraceStrategy traceStrategy)
{
    item i = firstItem();
    while (i != endItem())
    {
        i = nextItem();
        traceStrategy.func(i);
        if (traceStrategy.crit(i))
            return;
    }
}

et

interface TraceStrategy {
   public boolean crit(item i);

   public void func(item i);
}

Vous voudriez probablement rendre cela générique, afin de ne pas être lié à item... mais vous avez compris l'idée.

1voto

Patricia Shanahan Points 11270

Créez une interface qui déclare les méthodes et nécessite une référence à un objet implémentant l'interface en argument. L'appelant peut créer l'objet en utilisant une classe interne anonyme.

1voto

mikera Points 63056

Vous pouvez faire fonctionner cette fonction trace parfaitement en Java en combinant quelques techniques :

  • Au lieu des "pointeurs de fonction", vos paramètres func et crit devraient être des instances d'objets qui implémentent une interface spécifique. Vous pouvez ensuite appeler une fonction dans cette interface sur l'objet i. En effet, il s'agit d'un Patron Visiteur avec deux paramètres visiteurs différents.
  • Vous avez également besoin d'un moyen de parcourir l'arbre. Vous pourriez implémenter un Iterator - cela vous donne un bon moyen de parcourir toute la structure. Alternativement, vous pourriez rendre trace récursif (il s'appelle lui-même sur les branches gauche et droite de l'arbre) et alors vous n'auriez pas besoin d'un itérateur.

La version de l'itérateur ressemblerait à ceci :

public void trace(IFunction func, ICriteria crit) {
    for (T i: this) {
        func.call(i);
        if (crit.test(i)) return;
    }
}

Ici, T est le type d'élément de la collection, et call et test sont les définitions de fonction dans les interfaces IFunction et ICriteria respectivement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X