Java Reference
In-Depth Information
In the context of lambda expressions, many of the higher-order functions that we've en-
countered enable a dependency inversion. A function such as map allows us to reuse code for
the general concept of transforming a stream of values between different specific transforma-
tions. The map function doesn't depend upon the details of any of these specific transforma-
tions, but upon an abstraction. In this case, the abstraction is the functional interface Func-
tion .
A more complex example of dependency inversion is resource management. Obviously,
there are lots of resources that can be managed, such as database connections, thread pools,
files, and network connections. I'll use files as an example because they are a relatively
simple resource, but the principle can easily be applied to more complex resources within
your application.
Let's look at some code that extracts headings from a hypothetical markup language where
each heading is designated by being suffixed with a colon ( : ). Our method is going to extract
the headings from a file by reading the file, looking at each of the lines in turn, filtering out
the headings, and then closing the file. We shall also wrap any Exception related to the file
I/O into a friendly domain exception called a HeadingLookupException . The code looks
like Example 8-42 .
Example 8-42. Parsing the headings out of a file
public
public List < String > findHeadings ( Reader input ) {
try
try ( BufferedReader reader = new
new BufferedReader ( input )) {
return
return reader . lines ()
. filter ( line -> line . endsWith ( ":" ))
. map ( line -> line . substring ( 0 , line . length () - 1 ))
. collect ( toList ());
} catch
catch ( IOException e ) {
throw
throw new
new HeadingLookupException ( e );
}
}
Unfortunately, our heading-finding code is coupled with the resource-management and file-
handling code. What we really want to do is write some code that finds the headings and del-
egates the details of a file to another method. We can use a Stream<String> as the abstrac-
tion we want to depend upon rather than a file. A Stream is much safer and less open to ab-
use. We also want to be able to a pass in a function that creates our domain exception if
there's a problem with the file. This approach, shown in Example 8-43 , allows us to segreg-
ate the domain-level error handling from the resource management-level error handling.
Search WWH ::




Custom Search