Réflexion sur la mise en place du patron de conception Function Object en Java,
Un tutoriel de Yann Caron
Le 2013-05-17 15:00:44, par CyaNnOrangehead, Rédacteur
Bonjour à tous,
Je vous propose un petit article intitulé : « Fonction Object Design pattern - Tutoriel sur les foncteurs - En attendant les lambdas de Java 8 » disponible ici : http://caron-yann.developpez.com/tut...osures-java-8/
Ce tutoriel ce compose comme suit :
Cette dernière partie est le résultat d'une discussion ouverte avec, entre autrez, Thierry, que je continuerai très volontiers avec vous.
Elle démontre que Java, depuis la version 5 de son framework, n'a rien à envier à des langages tels que Ruby. Et qu'il n'est pas nécessaire de ce mettre à Groovy pour faire du fonctionnel avec le langage Java.
Et n'oubliez pas de commenter cet article. Vos retours nous aident à améliorer nos publications.
Bonne lecture.
Je vous propose un petit article intitulé : « Fonction Object Design pattern - Tutoriel sur les foncteurs - En attendant les lambdas de Java 8 » disponible ici : http://caron-yann.developpez.com/tut...osures-java-8/
Ce tutoriel ce compose comme suit :
- une présentation du design pattern « function object » ou plus connu sous le nom de foncteur ;
- une implémentation de celui-ci en Java qui respecte le principe de signature des méthodes en s'appuyant sur les génériques (ce qui n'est pas tout à fait le cas de librairies telles que Guava) ;
- des cas concrets d'utilisations comme la création de callbacks, l’ajout de méthodes fonctionnelles aux listes (each et map-filter-reduce), parcours depth-first, décorateur fonctionnel et conteneurs IOC.
Cette dernière partie est le résultat d'une discussion ouverte avec, entre autrez, Thierry, que je continuerai très volontiers avec vous.
Elle démontre que Java, depuis la version 5 de son framework, n'a rien à envier à des langages tels que Ruby. Et qu'il n'est pas nécessaire de ce mettre à Groovy pour faire du fonctionnel avec le langage Java.
Et n'oubliez pas de commenter cet article. Vos retours nous aident à améliorer nos publications.
Bonne lecture.
-
professeur shadokoMembre chevronnéIl me semblerait intéressant de compléter avec deux choses:
- un véritable pattern Commande
Code : 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public interface CommandFor<T> { public void invokeOn(T instance); } public class CommandForDoer implements CommandFor<Doer>, Serializable { private final String aString ; private final int anInt ; public CommandForDoer(String aString, int anInt) { this.aString = aString; this.anInt = anInt; } @Override public void invokeOn(Doer instance) { instance.show(aString, anInt); } }
- un exemple de dynamic Proxyle 23/05/2013 à 17:21 -
CyaNnOrangeheadRédacteurExcellent, effectivement il y a moyen de faire des trucs pas mal en combinant les deux techniques.
Je regarde dés que j'ai un moment !le 23/05/2013 à 17:39 -
CyaNnOrangeheadRédacteurVoici également la résolution d'un problème que je voulais ajouter :
Compter le nombre de fois ou l'on trouve un mot dans un texte.
Le principe est le suivant :
Un premier map/reduce s'occupe du split "\n"
Un second, à l'intérieur s'occupe de compter les mots "elements"
Voilà ce que ça donne :
Code : 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49public void testCountWords() throws Exception { String csv = "" + "element 1.1, element 1.2, element 1.3, element 1.4\n" + "element 2.1, element 2.2\n" + "element 3.1, element 3.2, element 3.3\n" + "element 4.1, element 4.2, element 4.3, element 4.4, element 4.5\n" + ""; int count = split(csv, "\n").<Integer>map(new Function<Integer, Arguments2<String, Integer>>() { @Override public Integer invoke(Arguments2<String, Integer> arguments) { // the line System.out.println("Line : " + arguments.getArgument1()); return split(arguments.getArgument1(), " ").<Integer>map(new Function<Integer, Arguments2<String, Integer>>() { @Override public Integer invoke(Arguments2<String, Integer> arguments) { // the element System.out.println("Word :" + arguments.getArgument1()); if ("element".equalsIgnoreCase(arguments.getArgument1())) { return 1; } else { return 0; } } }).reduce(new Function<Integer, Arguments2<Integer, Integer>>() { @Override public Integer invoke(Arguments2<Integer, Integer> arguments) { return arguments.getArgument1() + arguments.getArgument2(); } }); } }).reduce(new Function<Integer, Arguments2<Integer, Integer>>() { @Override public Integer invoke(Arguments2<Integer, Integer> arguments) { return arguments.getArgument1() + arguments.getArgument2(); } }); System.out.println("number of 'element' word in text : " + count); }
le 23/05/2013 à 17:54 -
LDPDCMembre régulierMerci pour cet article complet mais je ne vois pas très bien l'intérêt de la solution proposée: y-a-t-il un cas d'utilisation réel emblématique qui permettrait de bien comprendre l'utilité concrète de cette implémentation?le 08/10/2013 à 22:17
-
CyaNnOrangeheadRédacteurSalut LDPDC,
Déjà, cet article est un ensemble de réflexions sur le design pattern Function Object.
Le cas concret emblématique c'est la manipulation des listes qui est présentée dans le chapitre map / filter / reduce
Cette approche est complètement différente de l'approche impérative classique de java (et autres).
Le but en soi du fonctionnel à ce niveau est de rendre plus concis et plus lisible le code pour gérer des listes (évidement, avec les générique imposés par java, comme ça, ça ne saute pas aux yeux).
Guava, bien qu'un petit peu plus limité au niveaux des définitions des foncteurs, propose une très bonne implémentation de ce que j'expose.
Ce week-end, j'ai essayé le langage Scala qui est fondé sur une fusion fonctionnel / objet, on y retrouve tout ça et bien plus. J'y ai écrit les exemples de cet article, et là pour le coup c'est le code source est vraiment concis (moins de 5 lignes pour faire la moyenne des âges chiens mâles d'une liste d'individus).
5 lignes également pour le parcours d'un csv.
L'autre intérêt de tout ceci, c'est surtout de cacher l'implémentation des manipulations de listes à l'utilisateur. Ca permet, entre autre, de faire joujou avec les threads à son insu de façon à optimiser de façon transparent pour l'utilisateur. Un exemple en annexe illustre ceci.le 09/10/2013 à 0:04 -
Nico02Membre expérimentéUn article vraiment intéressant !
J'ai bien aimé le coté "réflexion à haute voix". Ça apporte à mon sens une facilité de lecture et on comprends tout de suite dans quoi on met les pieds.
En bref, je vais me laisser le temps de digérer tout ça, et je pense bien rajouter ce pattern dans ma boite à outils.
Cdt.le 09/10/2013 à 10:18 -
CyaNnOrangeheadRédacteurOui foncteur est un pattern ultra utile quand on y a goûter.
Après mon implémentation est très puriste sur les arguments, leur nombre et leurs types, mais la contrepartie c'est qu'elle oblige à créer énormément d'objet Arguments et c'est pas idéal pour les performances.
Un interface de ce type est plus rapide :Code : 1
2
3
4
5
6
7
8public interface Function1 <R, A1> { R invoke (A1 arg1); } public interface Function2 <R, A1, A2> { R invoke (A1 arg1, A2 arg2); }
le 09/10/2013 à 17:35