-
Notifications
You must be signed in to change notification settings - Fork 135
Reader : functional dependency injection
The Reader class allows us to transform functions, by composing them.
E.g given two functions, one that maps from T to R and another from R to R1..
Function<T, R> fn;
Function<? super R, ? extends R1> fn2;
We can combine them to create a single function that maps from T to R1
Function<T,R1> composed = fn.andThen(fn2)
Reader allows us to map and flatMap functions in the manner of elements within a Stream, composing them together into a single function as we do so.
Normally in Java we will inject our dependencies into a class, perhaps using a framework or by a chain of factory methods, so that they are there when we execute a method that needs them. An alternative approach is, rather than execute the code that needs the dependency immediately, rather return a Function that accepts the dependency needed and have that Function execute the code.
e.g. a traditional Java service
class Service{
DAO userDao;
public User loadUser(long id){
return dao.loadUser(id);
}
}
could become
class Service{
public Function<Dao,User> loadUser(long id){
return dao->dao.loadUser(id);
}
}
Further more if we refactor this to use [Reader] instead of Function (Reader extends Function and is also a FunctionalInterface) we can manipulate the returned Function and build a chain of method calls, that for example, work with the returned User - even though we won't have the User until we supply the DAO and execute the function at the very top level.
class Service{
public Reader<Dao,User> loadUser(long id){
return dao->dao.loadUser(id);
}
}
oops - my bad