SlideShare uma empresa Scribd logo
1 de 157
Baixar para ler offline
Alonso Torres @alotor
Design Patterns
“
”
Cada patrón describe un problema recurrente en nuestro
entorno, así como la solución a ese problema, de tal modo que se
pueda aplicar esta solución un millón de veces, sin hacer lo mismo
dos veces.
- Christopher Alexander, A Pattern Language
Los patrones definen:
soluciones a problemas frecuentes
¿
?
Son las soluciones con Java 8 las
mismas que con versiones anteriores
λ
Alonso Torres
@alotor
mobro.co/alotor
El camino hacia
1996
1990 1995 2000 2005 2010 2015
1.0 1.2 1.4 5 6 7 81.3
1994
1990 1995 2000 2005 2010 2015
1.0 1.2 1.4 5 6 7 81.3
1998 - J2SE 1.2
1990 1995 2000 2005 2010 2015
1.0 1.2 1.4 5 6 7 81.3
Adopción masiva del
lenguaje
2004 - J2SE 5.0
1990 1995 2000 2005 2010 2015
1.0 1.2 1.4 5 6 7 81.3
Genéricos
Anotaciones
Enumerados
Nueva sintaxis
Concurrencia
1990 1995 2000 2005 2010 2015
1.0 1.2 1.4 5 6 7 81.3
1990 1995 2000 2005 2010 2015
1.0 1.2 1.4 5 6 7 81.3
2011 - Java SE 7
1990 1995 2000 2005 2010 2015
1.0 1.2 1.4 5 6 7 81.3
InvokeDynamic
NIO 2
Nueva concurrencia
2014 - Java SE 8
1990 1995 2000 2005 2010 2015
1.0 1.2 1.4 5 6 7 81.3
Java 8
● Lambda expressions
● Functional interfaces
● Default methods
● Streams
Java 8
● Lambda expressions
● Functional interfaces
● Default methods
● Streams
Las lambdas son lo mejor que le ha
pasado a Java desde….
Las lambdas son lo mejor que le ha
pasado a Java.
1990 1995 2000 2005 2010 2015
1.0 1.2 1.4 5 6 7 81.3
C#
1990 1995 2000 2005 2010 2015
1.0 1.2 1.4 5 6 7 81.3
ActionScript Groovy Perl
C# Haskell PHP
C++ JavaScript Python
Clojure Lisp R
Curl Logtalk Racket
D Lua Ruby
Dart Mathematica Scala
Dylan Maple Scheme
Erlang Matlab Smalltalk
Elixir Maxima Standard ML
F# OCaml TypeScript
Go Object Pascal Tcl
Gosu Objective-C VisualBasic .NET
Fortran
C
Ada
Cobol
Fortran 1957
C 1969
Ada 1977
Cobol 1989
15%
20%
Features
● Lambda expressions
● Functional interfaces
● Default methods
● Streams
Lambdas: funciones anónimas
public Integer addition(Integer x, Integer y) {
return x + y;
}
public void sayHello(String name) {
System.out.println("Hello " + name);
}
public Float giveMePi() {
return 3.15f;
}
public Integer addition(Integer x, Integer y) {
return x + y;
}
public void sayHello(String name) {
System.out.println("Hello " + name);
}
public Float giveMePi() {
return 3.15f;
}
(Integer x, Integer y) -> {
return x + y;
};
(String name) -> {
System.out.println("Hello" + name);
};
() -> {
return 3.15f;
};
(Integer x, Integer y) -> x + y;
(String name) -> {
System.out.println("Hello" + name);
};
() -> 3.15f
(Integer x, Integer y) -> x + y;
(String name) -> {
System.out.println("Hello" + name);
};
() -> 3.15f
PARÁMETROS CUERPO
(parameters) -> body;
(Integer x, Integer y) -> x + y;
(String name) -> System.out.println("Hello" + name);
() -> 3.15f
Thread th = new Thread(new Runnable(){
@Override
public void run() {
System.out.println(">> Another thread"));
}
});
th.start();
Creando hilos
Thread th = new Thread(() ->
System.out.println(">> Another thread"));
th.start();
Creando hilos
Me váis a llamar loco
pero…
…en ocasiones veo
patrones
Thread th = new Thread(() ->
System.out.println(">> Another thread"));
th.start();
Creando hilos
Client Invoker
Receiver
+action()
ConcreteCommand
+execute()
Command
+execute()
Command
PATRÓN
new Invoker().addCommand(new Command() {
@Override
public void execute() {
receiver.action();
}
});
new Transaction().doWithTransaction(new Command() {
@Override
public void execute() {
myBusinessLogic.calculateInterests();
}
});
new Context().doAsync(new Command() {
@Override
public void execute() {
networkManager.downloadFile();
}
});
Client Invoker
Receiver
+action()
ConcreteCommand
+execute()
Command
+execute()
Client Invoker
Receiver
+action()
ConcreteCommand
+execute()
Command
+execute()
Lambda
new Invoker().addCommand(new Command() {
@Override
public void execute() {
receiver.action();
}
});
new Invoker().addCommand(new Command() {
@Override
public void execute() {
receiver.action();
}
});
new Invoker().addCommand(
() -> receiver.action();
);
surely,
we
can
do
better
new Invoker().addCommand(
receiver::action
);
Method Reference
Method Reference:
Transformar un método en una
lambda
() -> receiver.action()
(el) -> el.toString()
() -> Runtime.getInstance()
() -> new Receiver()
() -> receiver.action()
(el) -> el.toString()
() -> Runtime.getInstance()
() -> new Receiver()
() -> receiver.action() receiver::action
(el) -> el.toString() Object::toString
() -> Runtime.getInstance() Runtime::getInstance
() -> new Receiver() Reciver::new
Instance method reference
(objeto concreto)
Instance method reference
(cualquier objeto)
Static method reference
Constructor reference
receiver::action
Object::toString
Runtime::getInstance
Reciver::new
(Integer x, Integer y) ->
receiver.action(x, y)
(Integer x, Integer y) ->
Math.max(x, y)
(String str) ->
new String(str)
(Integer x, Integer y) ->
receiver.action(x, y)
receiver::action
(Integer x, Integer y) ->
Math.max(x, y)
Math::max
(String str) ->
new String(str)
String::new
new Transaction().doWithTransaction(
myBusinessLogic::calculateInterests
);
new ThreadPool().doInThread(
networkManager::downloadFile
);
new Transaction().doWithTransaction(
networkManager::downloadFile
);
new ThreadPool().doInThread(
myBusinessLogic::calculateInterests
);
Client Invoker
Receiver
+action()
ConcreteCommand
+execute()
Command
+execute()
Client Invoker
Receiver
+action()
ConcreteCommand
+execute()
Command
+execute()
Client Invoker
Receiver
+action()
Command
+execute()
(Integer x, Integer y) -> x + y;
(String name) -> System.out.println("Hello" + name);
() -> 3.15f
¿Qué TIPO tienen las lambdas?
Object addition =
(Integer x, Integer y) -> x + y;
Object sayHello =
(String name) -> System.out.println("Hello" + name);
Object giveMePi =
() -> 3.15f
¿Qué TIPO tienen las lambdas?
The target type of this expression must be a
functional interface
Java 8
● Lambda expressions
● Functional interfaces
● Default methods
● Streams
(Integer x, Integer y) -> x + y;
(String name) -> System.out.println("Hello" + name);
() -> 3.15f
(Integer x, Integer y) -> x + y;
(String name) -> System.out.println("Hello" + name);
() -> 3.15f
Integer addition(Integer x, Integer y)
void sayHello(String name)
Float giveMePi()
Functional interfaces
public interface Addition {
Integer addition(Integer x, Integer y);
}
public interface SayHello {
void sayHello(String name);
}
public interface GiveMePi {
Float giveMePi();
}
Functional interfaces
public interface Addition {
public Integer addition(Integer x, Integer y);
}
1 sólo método
Functional interfaces
public interface Addition {
public Integer addition(Integer x, Integer y);
}
Addition addition =
(Integer x, Integer y) -> x + y;
public interface Addition {
public Integer addition(Integer x, Integer y);
}
public interface Operation<T extends Number> {
public T do(T x, T y);
}
Operation<Integer> addition =
(Integer x, Integer y) -> x + y;
PROBLEMA
Sólo funciona con interfaces
● NO pueden ser clases
● NI clases abstractas
Java 8
● Lambda expressions
● Functional interfaces
● Default methods
● Streams
Default Methods
public interface Addition {
public Integer addition(Integer x, Integer y);
default Integer substraction(Integer x, Integer y) {
return addition(x, -y);
}
}
public interface Addition {
public Integer addition(Integer x, Integer y);
}
Addition addition =
(Integer x, Integer y) -> x + y;
Si tenemos que definir una “Functional Interface”
por cada lambda...
¿Qué hemos ganado?
Java 8
viene con las interfaces más comunes
DE SERIE
import java.util.function.*
BiConsumer<T,U> IntBinaryOperator LongUnaryOperator
BiFunction<T,U,R> IntConsumer ObjDoubleConsumer<T>
BinaryOperator<T> IntFunction<R> ObjIntConsumer<T>
BiPredicate<T,U> IntPredicate ObjLongConsumer<T>
BooleanSupplier IntSupplier Predicate<T>
Consumer<T> IntToDoubleFunction Supplier<T>
DoubleBinaryOperator IntToLongFunction ToDoubleBiFunction<T,U>
DoubleConsumer IntUnaryOperator ToDoubleFunction<T>
DoubleFunction<R> LongBinaryOperator ToIntBiFunction<T,U>
DoublePredicate LongConsumer ToIntFunction<T>
DoubleSupplier LongFunction<R> ToLongBiFunction<T,U>
DoubleToIntFunction LongPredicate ToLongFunction<T>
DoubleToLongFunction LongSupplier UnaryOperator<T>
DoubleUnaryOperator LongToDoubleFunction
Function<T,R> LongToIntFunction
(Integer x, Integer y) -> x + y;
(String name) -> System.out.println("Hello" + name);
() -> 3.15f
¿Qué TIPO tienen?
public Integer addition(Integer x, Integer y)
public void sayHello(String name)
public Float giveMePi()
BiConsumer<T,U> IntBinaryOperator LongUnaryOperator
BiFunction<T,U,R> IntConsumer ObjDoubleConsumer<T>
BinaryOperator<T> IntFunction<R> ObjIntConsumer<T>
BiPredicate<T,U> IntPredicate ObjLongConsumer<T>
BooleanSupplier IntSupplier Predicate<T>
Consumer<T> IntToDoubleFunction Supplier<T>
DoubleBinaryOperator IntToLongFunction ToDoubleBiFunction<T,U>
DoubleConsumer IntUnaryOperator ToDoubleFunction<T>
DoubleFunction<R> LongBinaryOperator ToIntBiFunction<T,U>
DoublePredicate LongConsumer ToIntFunction<T>
DoubleSupplier LongFunction<R> ToLongBiFunction<T,U>
DoubleToIntFunction LongPredicate ToLongFunction<T>
DoubleToLongFunction LongSupplier UnaryOperator<T>
DoubleUnaryOperator LongToDoubleFunction
Function<T,R> LongToIntFunction
import java.util.function.*
BinaryOperator<Integer> addition =
(Integer x, Integer y) -> x + y;
Consumer<String> sayHi =
(String name) -> System.out.println("Hello" + name);
Supplier<Float> giveMePi =
() -> 3.15f
BinaryOperator<Integer> addition =
(x, y) -> x + y;
Consumer<String> sayHi =
(name) -> System.out.println("Hello" + name);
Supplier<Float> giveMePi =
() -> 3.15f
Thread th = new Thread(() ->
System.out.println(">> Another thread"));
th.start();
java.lang.Runnable
JButton button = new JButton("Button");
button.addActionListener((event) ->
System.out.println("Mouse: " + event);
);
java.awt.ActionListener
Observer
PATRÓN
ConcreteObserverA
+notify()
ConcreteObserverB
+notify()
Observer
+notify()
ObservedClass
+registerObserver()
+unregisterObserver()
+notifyObservers()
Functional Interface
Lambdas!
@FunctionalInterface
public static interface Observer {
public void notify(Object change);
}
@FunctionalInterface
public static interface Observer {
public void notify(Object change);
}
@FunctionalInterface
public static interface Observer {
public void notify(Object change);
}
El compilador fallará si no
cumple con las condiciones
de una FI.
@FunctionalInterface
public static interface Observer {
public void notify(Object change);
}
El compilador fallará si no
cumple con las condiciones
de una FI.
Tu yo del futuro te lo agradecerá
public static class ObservedClass {
private List<Observer> observers = new LinkedList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyChange(Object change) {
observers.forEach((o) -> o.notify(change));
}
}
public static class ObservedClass {
private List<Observer> observers = new LinkedList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyChange(Object change) {
observers.forEach((o) -> o.notify(change));
}
}
Una estructura de datos que
guarda lambdas.
public static class ObservedClass {
private List<Observer> observers = new LinkedList<>();
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
public void notifyChange(Object change) {
observers.forEach((o) -> o.notify(change));
}
}
Nuevo método de Java 8
observed.addObserver((change) -> {
new Thread(UIThread::update).start()
});
sbj.notifyChange("Change");
Hipótesis
¿Puede haber un patrón de más alto nivel?
new Invoker().addCommand(receiver::action);
observed.addObserver(receiver::action);
Pasar comportamiento como argumentos
● El comportamiento se ejecutará en otro contexto
● “Separation of concerns”
● También conocido como: High Order Functions
new Invoker().addCommand(receiver::action);
observed.addObserver(receiver::action);
List<Person> personList = new LinkedList<>();
Collections.sort(
personList,
(p1, p2) -> p1.age - p2.age
);
java.lang.Comparable<T>
List<Person> personList = new LinkedList<>();
Collections.sort(
personList,
(p1, p2) -> p1.age - p2.age
);
java.lang.Comparable<T>
DATOS
COMPORTAMIENTO
Strategy
PATRÓN
Collections.sort(
list,
(p1, p2) -> p1.getAge() - p2.getAge());
Collections.sort(
list,
(p1, p2) -> p1.getName().compareTo(p2.getName()));
Collections.sort(
list,
(p1, p2) -> -p1.getName().compareTo(p2.getName()));
Reusing lambdas
class PersonSortCriterias {
public static int sortByAge(Person p1, Person p2) {
return p1.getAge() - p2.getName();
}
public static int sortByName(Person p1, Person p2) {
return p1.getName().compareTo(p2.getName());
}
public static int sortByNameReverse(Person p1, Person p2) {
return -p1.getName().compareTo(p2.getName());
}
}
Collections.sort(
list,
PersonSortCriterias::sortByAge);
Collections.sort(
list,
PersonSortCriterias::sortByName);
Collections.sort(
list,
PersonSortCriterias::sortByNameReverse);
Set<Person> = new TreeSet<>(
PersonSortCriterias::sortByAge
);
Person theOlder = Collections.max(
list,
PersonSortCriterias::sortByAge
);
list.sort(PersonSortCriterias::sortByAge);
Java 8
● Lambda expressions
● Functional interfaces
● Default methods
● Streams
Java 8
● Lambda expressions
● Functional interfaces
● Default methods
● Streams
Iterator
PATRÓN
for (String str : list) {
System.out.println(str);
}
for (String str : list) {
if (str.length <= 5) {
System.out.println(str);
}
}
for (String str : Collections.sort(list)) {
if (str.length <= 5) {
System.out.println(str);
}
}
for (String str : Collections.sort(list).sublist(0, 10)) {
if (str.length <= 5) {
System.out.println(str);
}
}
for (String str : Collections.sort(list).sublist(0, 10)) {
if (str.length <= 5) {
System.out.println(str.toUpperCase());
}
}
Problemas
● Susceptible a errores
● Difícil de razonar
● Difícil de reutilizar
Streams
● Interfaz fluida
● Evaluación perezosa
● Iterable
● Aprovechan toda la expresividad de las
lambdas
list.stream()
.forEach(System.out::println);
list.stream()
.filter(s -> s.length <= 5)
.forEach(System.out::println);
list.stream()
.filter(s -> s.length <= 5)
.sorted()
.forEach(System.out::println);
list.stream()
.filter(s -> s.length <= 5)
.sorted()
.limit(10)
.forEach(System.out::println);
list.parallelStream()
.filter(s -> s.length <= 5)
.sorted()
.limit(10)
.forEach(System.out::println);
Funciones importantes
● Map
● Filter
● Reduce
MAP - FILTER - REDUCE
list.stream()
.map(String::toUpperCase)
"banana"
"apple"
"pear"
"pineapple"
"lemon"
"mango"
"raspberry"
"melon"
"BANANA"
"APPLE"
"PEAR"
"PINEAPPLE"
"LEMON"
"MANGO"
"RASPBERRY"
"MELON"
MAP - FILTER - REDUCE
list.stream()
.filter(s -> s.length <= 5)
"banana"
"apple"
"pear"
"pineapple"
"lemon"
"mango"
"raspberry"
"melon"
"apple"
"pear"
"lemon"
"mango"
"melon"
MAP - FILTER - REDUCE
list.stream()
.reduce("", (acc, elem) -> acc + ", " + elem);
"banana"
"apple"
"pear"
"pineapple"
"lemon"
"mango"
"raspberry"
"melon"
"banana,apple,pear,pineapple,...
Chain of
responsibility
PATRÓN
HANDLER HANDLER HANDLER HANDLER HANDLER
request
HANDLER HANDLER HANDLER HANDLER HANDLERrequest
HANDLER HANDLER HANDLER HANDLER HANDLERrequest
HANDLER HANDLER HANDLER HANDLER HANDLER
request
@FunctionalInterface
public interface Handler {
public Request handleRequest(Request req);
}
@FunctionalInterface
public interface Handler extends Function<Request, Request> {
}
List<Handler> chain = new LinkedList<>();
chain.add(Request::session);
chain.add(Request::securityCheck);
chain.add(Request::cookies);
chain.add(Request::getParameters);
List<Handler> chain = new LinkedList<>();
chain.add(Request::session);
chain.add(Request::securityCheck);
chain.add(Request::cookies);
chain.add(Request::getParameters);
Request req = new Request();
Request processed =
chain.stream()
.reduce(initial value,
accumulation function)
List<Handler> chain = new LinkedList<>();
chain.add(Request::session);
chain.add(Request::securityCheck);
chain.add(Request::cookies);
chain.add(Request::getParameters);
Request req = new Request();
Request processed =
chain.stream()
.reduce(req,
accumulation function)
List<Handler> chain = new LinkedList<>();
chain.add(Request::session);
chain.add(Request::securityCheck);
chain.add(Request::cookies);
chain.add(Request::getParameters);
Request req = new Request();
Request processed =
chain.stream()
.reduce(req,
(old, handler) -> handler.apply(old))
HANDLER HANDLER HANDLER HANDLER HANDLER
request
HANDLER HANDLER HANDLER HANDLER HANDLER
request
CHAIN (HANDLER)
List<Handler> filters = new LinkedList<>();
filters.add(Request::session);
filters.add(Request::securityCheck);
filters.add(Request::cookies);
filters.add(Request::getParameters);
Handler filterChain =
filters.stream()
.reduce(
initial value,
accumulation function);
List<Handler> filters = new LinkedList<>();
filters.add(Request::session);
filters.add(Request::securityCheck);
filters.add(Request::cookies);
filters.add(Request::getParameters);
Handler filterChain =
filters.stream()
.reduce(
(r) -> r,
accumulation function);
List<Handler> filters = new LinkedList<>();
filters.add(Request::session);
filters.add(Request::securityCheck);
filters.add(Request::cookies);
filters.add(Request::getParameters);
Handler filterChain =
filters.stream()
.reduce(
(r) -> r,
(f1, f2) -> f1.andThen(f2));
List<Handler> filters = new LinkedList<>();
filters.add(Request::session);
filters.add(Request::securityCheck);
filters.add(Request::cookies);
filters.add(Request::getParameters);
Handler filterChain =
filters.stream()
.reduce(
Function.identity(),
Function::andThen);
System.out.println("nProcessing request 1");
Request r1 = chain.apply(new Request());
System.out.println("nProcessing request 2");
Request r2 = chain.apply(new Request());
Processing request 1
>> process session
>> process securityCheck
>> process cookies
>> process getParameters
Processing request 2
>> process session
>> process securityCheck
>> process cookies
>> process getParameters
¯_(ツ)_/¯
Java SE 8
● Lambda expressions
● Functional interfaces
● Default methods
● Streams
Patrones
● Command
● Strategy
● Observer
● Iterator
● Chain of responsibility
Los patrones definen:
soluciones a problemas frecuentes
Problema
● El comportamiento y el contexto son diferentes
● Encapsular los datos
● Composición de comportamiento
Solución
● High order functions (Lambdas)
Las lambdas son lo mejor que le ha
pasado a Java.
Sobre los hombros de gigantes
Mario Fusco Venkat Subramaniam Samir Talwar
https://youtu.be/K6BmGBzIqW0 https://vimeo.com/122645679https://youtu.be/8qcHPEyLkPE
@alotor
mobro.co/alotor
¿Preguntas?
@alotor
Referencias
● https://en.wikipedia.org/wiki/Java_version_history
● http://www.studytrails.com/java/java8/Java8_Lambdas_FunctionalProgramming.jsp
● https://blog.idrsolutions.com/2015/02/java-8-method-references-explained-5-minutes/
● http://www.infoq.com/articles/Java-8-Lambdas-A-Peek-Under-the-Hood
● http://www.javaworld.com/article/2078675/core-java/design-patterns--the-big-picture--part-2--gang-
of-four-classics-revisited.html
● http://stackoverflow.com/questions/1673841/examples-of-gof-design-patterns-in-javas-core-libraries
● https://www.questers.com/sites/all/themes/questers/sec_presentation/java8lambdas.html
● http://www.slideshare.net/jaxlondon2012/lambda-a-peek-under-the-hood-brian-goetz
● http://www.infoq.com/presentations/lambda-invokedynamic?
utm_source=infoq&utm_medium=videos_homepage&utm_campaign=videos_row1
● http://www.slideshare.net/DaewonJeong/scala-is-java8next
● http://programmers.stackexchange.com/questions/173441/what-triggered-the-popularity-of-lambda-
functions-in-modern-mainstream-programmi
● http://www.infoq.com/presentations/A-Brief-History-of-the-Java-World
Referencias
● http://j2objc.org/blog/2015/08/07/lambdas-in-java-8-dysfunctional-interfaces.html
● http://gafter.blogspot.com.es/2006/08/closures-for-java.html
● http://www.javaworld.com/article/2077569/core-java/java-tip-68--learn-how-to-implement-the-
command-pattern-in-java.html
● http://www.slideshare.net/mariofusco/fp-in-java-project-lambda-and-beyond?qid=11ae9463-c2e3-
4c54-842f-b228ce109200&v=default&b=&from_search=12
● http://www.norvig.com/design-patterns/design-patterns.pdf
● http://www.techempower.com/blog/2013/03/26/everything-about-java-8/
● http://www.oracle.com/technetwork/server-storage/ts-4961-159222.pdf
● http://talks.samirtalwar.com/design-patterns-in-the-21st-century.html

Mais conteúdo relacionado

Mais procurados

Monadologie
MonadologieMonadologie
Monadologieleague
 
Kotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime PerformanceKotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime Performanceintelliyole
 
Java 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardJava 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardMario Fusco
 
The Ring programming language version 1.8 book - Part 37 of 202
The Ring programming language version 1.8 book - Part 37 of 202The Ring programming language version 1.8 book - Part 37 of 202
The Ring programming language version 1.8 book - Part 37 of 202Mahmoud Samir Fayed
 
The Ring programming language version 1.4.1 book - Part 9 of 31
The Ring programming language version 1.4.1 book - Part 9 of 31The Ring programming language version 1.4.1 book - Part 9 of 31
The Ring programming language version 1.4.1 book - Part 9 of 31Mahmoud Samir Fayed
 
The Ring programming language version 1.5.2 book - Part 31 of 181
The Ring programming language version 1.5.2 book - Part 31 of 181The Ring programming language version 1.5.2 book - Part 31 of 181
The Ring programming language version 1.5.2 book - Part 31 of 181Mahmoud Samir Fayed
 
Demystifying functional programming with Scala
Demystifying functional programming with ScalaDemystifying functional programming with Scala
Demystifying functional programming with ScalaDenis
 
The Ring programming language version 1.5.1 book - Part 31 of 180
The Ring programming language version 1.5.1 book - Part 31 of 180The Ring programming language version 1.5.1 book - Part 31 of 180
The Ring programming language version 1.5.1 book - Part 31 of 180Mahmoud Samir Fayed
 
The Ring programming language version 1.2 book - Part 21 of 84
The Ring programming language version 1.2 book - Part 21 of 84The Ring programming language version 1.2 book - Part 21 of 84
The Ring programming language version 1.2 book - Part 21 of 84Mahmoud Samir Fayed
 
One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them AllJohn De Goes
 
Halogen: Past, Present, and Future
Halogen: Past, Present, and FutureHalogen: Past, Present, and Future
Halogen: Past, Present, and FutureJohn De Goes
 

Mais procurados (20)

Lec1
Lec1Lec1
Lec1
 
Monadologie
MonadologieMonadologie
Monadologie
 
Kotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime PerformanceKotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime Performance
 
Java 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forwardJava 7, 8 & 9 - Moving the language forward
Java 7, 8 & 9 - Moving the language forward
 
The Ring programming language version 1.8 book - Part 37 of 202
The Ring programming language version 1.8 book - Part 37 of 202The Ring programming language version 1.8 book - Part 37 of 202
The Ring programming language version 1.8 book - Part 37 of 202
 
Scala taxonomy
Scala taxonomyScala taxonomy
Scala taxonomy
 
The Ring programming language version 1.4.1 book - Part 9 of 31
The Ring programming language version 1.4.1 book - Part 9 of 31The Ring programming language version 1.4.1 book - Part 9 of 31
The Ring programming language version 1.4.1 book - Part 9 of 31
 
Lec3
Lec3Lec3
Lec3
 
Clojure intro
Clojure introClojure intro
Clojure intro
 
Sneaking inside Kotlin features
Sneaking inside Kotlin featuresSneaking inside Kotlin features
Sneaking inside Kotlin features
 
The Ring programming language version 1.5.2 book - Part 31 of 181
The Ring programming language version 1.5.2 book - Part 31 of 181The Ring programming language version 1.5.2 book - Part 31 of 181
The Ring programming language version 1.5.2 book - Part 31 of 181
 
Demystifying functional programming with Scala
Demystifying functional programming with ScalaDemystifying functional programming with Scala
Demystifying functional programming with Scala
 
Initial Java Core Concept
Initial Java Core ConceptInitial Java Core Concept
Initial Java Core Concept
 
The Ring programming language version 1.5.1 book - Part 31 of 180
The Ring programming language version 1.5.1 book - Part 31 of 180The Ring programming language version 1.5.1 book - Part 31 of 180
The Ring programming language version 1.5.1 book - Part 31 of 180
 
The Ring programming language version 1.2 book - Part 21 of 84
The Ring programming language version 1.2 book - Part 21 of 84The Ring programming language version 1.2 book - Part 21 of 84
The Ring programming language version 1.2 book - Part 21 of 84
 
An introduction to scala
An introduction to scalaAn introduction to scala
An introduction to scala
 
One Monad to Rule Them All
One Monad to Rule Them AllOne Monad to Rule Them All
One Monad to Rule Them All
 
Java Class Design
Java Class DesignJava Class Design
Java Class Design
 
Introduction to Kotlin
Introduction to KotlinIntroduction to Kotlin
Introduction to Kotlin
 
Halogen: Past, Present, and Future
Halogen: Past, Present, and FutureHalogen: Past, Present, and Future
Halogen: Past, Present, and Future
 

Semelhante a [Codemotion 2015] patrones de diseño con java8

New Functional Features of Java 8
New Functional Features of Java 8New Functional Features of Java 8
New Functional Features of Java 8franciscoortin
 
Functional Programming In Java
Functional Programming In JavaFunctional Programming In Java
Functional Programming In JavaAndrei Solntsev
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойSigma Software
 
The... Wonderful? World of Lambdas
The... Wonderful? World of LambdasThe... Wonderful? World of Lambdas
The... Wonderful? World of LambdasEsther Lozano
 
Mastering Kotlin Standard Library
Mastering Kotlin Standard LibraryMastering Kotlin Standard Library
Mastering Kotlin Standard LibraryNelson Glauber Leal
 
Functional programming ii
Functional programming iiFunctional programming ii
Functional programming iiPrashant Kalkar
 
Scala is java8.next()
Scala is java8.next()Scala is java8.next()
Scala is java8.next()daewon jeong
 
SeneJug java_8_prez_122015
SeneJug java_8_prez_122015SeneJug java_8_prez_122015
SeneJug java_8_prez_122015senejug
 
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...Akaks
 
Cocoa Design Patterns in Swift
Cocoa Design Patterns in SwiftCocoa Design Patterns in Swift
Cocoa Design Patterns in SwiftMichele Titolo
 
Introduction to new features in java 8
Introduction to new features in java 8Introduction to new features in java 8
Introduction to new features in java 8Raffi Khatchadourian
 
Scala Back to Basics: Type Classes
Scala Back to Basics: Type ClassesScala Back to Basics: Type Classes
Scala Back to Basics: Type ClassesTomer Gabel
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfHiroshi Ono
 

Semelhante a [Codemotion 2015] patrones de diseño con java8 (20)

New Functional Features of Java 8
New Functional Features of Java 8New Functional Features of Java 8
New Functional Features of Java 8
 
Functional Programming In Java
Functional Programming In JavaFunctional Programming In Java
Functional Programming In Java
 
Столпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай МозговойСтолпы функционального программирования для адептов ООП, Николай Мозговой
Столпы функционального программирования для адептов ООП, Николай Мозговой
 
The... Wonderful? World of Lambdas
The... Wonderful? World of LambdasThe... Wonderful? World of Lambdas
The... Wonderful? World of Lambdas
 
Mastering Kotlin Standard Library
Mastering Kotlin Standard LibraryMastering Kotlin Standard Library
Mastering Kotlin Standard Library
 
Java gets a closure
Java gets a closureJava gets a closure
Java gets a closure
 
functions
functionsfunctions
functions
 
Functional programming ii
Functional programming iiFunctional programming ii
Functional programming ii
 
Scala is java8.next()
Scala is java8.next()Scala is java8.next()
Scala is java8.next()
 
SeneJug java_8_prez_122015
SeneJug java_8_prez_122015SeneJug java_8_prez_122015
SeneJug java_8_prez_122015
 
Wien15 java8
Wien15 java8Wien15 java8
Wien15 java8
 
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
documents.pub_new-features-in-java-8-it-jpoialjavanaitedwien15java8pdf-java-8...
 
Cocoa Design Patterns in Swift
Cocoa Design Patterns in SwiftCocoa Design Patterns in Swift
Cocoa Design Patterns in Swift
 
Introduction to new features in java 8
Introduction to new features in java 8Introduction to new features in java 8
Introduction to new features in java 8
 
Introduction to new features in java 8
Introduction to new features in java 8Introduction to new features in java 8
Introduction to new features in java 8
 
Scala Back to Basics: Type Classes
Scala Back to Basics: Type ClassesScala Back to Basics: Type Classes
Scala Back to Basics: Type Classes
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdfpragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
 

Mais de Alonso Torres

[Greach 17] make concurrency groovy again
[Greach 17] make concurrency groovy again[Greach 17] make concurrency groovy again
[Greach 17] make concurrency groovy againAlonso Torres
 
[Jbcn 2016] Garbage Collectors WTF!?
[Jbcn 2016] Garbage Collectors WTF!?[Jbcn 2016] Garbage Collectors WTF!?
[Jbcn 2016] Garbage Collectors WTF!?Alonso Torres
 
[Greach 2016] Down The RabbitMQ Hole
[Greach 2016] Down The RabbitMQ Hole[Greach 2016] Down The RabbitMQ Hole
[Greach 2016] Down The RabbitMQ HoleAlonso Torres
 
(Greach 2015) Dsl'ing your Groovy
(Greach 2015) Dsl'ing your Groovy(Greach 2015) Dsl'ing your Groovy
(Greach 2015) Dsl'ing your GroovyAlonso Torres
 
(Greach 2015) Decathlon Sport Meeting
(Greach 2015) Decathlon Sport Meeting(Greach 2015) Decathlon Sport Meeting
(Greach 2015) Decathlon Sport MeetingAlonso Torres
 
(Codemotion 2014) 20 lenguajes en 40 minutos
(Codemotion 2014) 20 lenguajes en 40 minutos(Codemotion 2014) 20 lenguajes en 40 minutos
(Codemotion 2014) 20 lenguajes en 40 minutosAlonso Torres
 
(Codemotion 2014) JVM GC: WTF?!
(Codemotion 2014) JVM GC: WTF?!(Codemotion 2014) JVM GC: WTF?!
(Codemotion 2014) JVM GC: WTF?!Alonso Torres
 
Understanding GORM (Greach 2014)
Understanding GORM (Greach 2014)Understanding GORM (Greach 2014)
Understanding GORM (Greach 2014)Alonso Torres
 

Mais de Alonso Torres (8)

[Greach 17] make concurrency groovy again
[Greach 17] make concurrency groovy again[Greach 17] make concurrency groovy again
[Greach 17] make concurrency groovy again
 
[Jbcn 2016] Garbage Collectors WTF!?
[Jbcn 2016] Garbage Collectors WTF!?[Jbcn 2016] Garbage Collectors WTF!?
[Jbcn 2016] Garbage Collectors WTF!?
 
[Greach 2016] Down The RabbitMQ Hole
[Greach 2016] Down The RabbitMQ Hole[Greach 2016] Down The RabbitMQ Hole
[Greach 2016] Down The RabbitMQ Hole
 
(Greach 2015) Dsl'ing your Groovy
(Greach 2015) Dsl'ing your Groovy(Greach 2015) Dsl'ing your Groovy
(Greach 2015) Dsl'ing your Groovy
 
(Greach 2015) Decathlon Sport Meeting
(Greach 2015) Decathlon Sport Meeting(Greach 2015) Decathlon Sport Meeting
(Greach 2015) Decathlon Sport Meeting
 
(Codemotion 2014) 20 lenguajes en 40 minutos
(Codemotion 2014) 20 lenguajes en 40 minutos(Codemotion 2014) 20 lenguajes en 40 minutos
(Codemotion 2014) 20 lenguajes en 40 minutos
 
(Codemotion 2014) JVM GC: WTF?!
(Codemotion 2014) JVM GC: WTF?!(Codemotion 2014) JVM GC: WTF?!
(Codemotion 2014) JVM GC: WTF?!
 
Understanding GORM (Greach 2014)
Understanding GORM (Greach 2014)Understanding GORM (Greach 2014)
Understanding GORM (Greach 2014)
 

Último

A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEarley Information Science
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 

Último (20)

A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 

[Codemotion 2015] patrones de diseño con java8