If you're interested in functional programming, you might also want to checkout my second blog which i'm actively working on!!

Thursday, March 28, 2013

Using the loan pattern in Java

In Java you often deal with a lot of boilerplate code. A typical example is
opening an inputstream, using the inputstream and next closing it. But this
simple use case takes writing quite a bit of code.Some of this boilerplate
can be factored out by using the loan pattern, where the bank connects a
producer and consumer and takes care of the heavy lifting. This code can be
further generalized using generics but for illustrating purposes it serves
as a nice example.
**************************************************
Consumer Interface *
**************************************************
public interface InputStreamConsumer {
void consume(InputStream in) throws Exception;
}
**************************************************
Producer Interface *
**************************************************
public interface InputStreamProducer {
InputStream produce() throws Exception;
}
**************************************************
Lender which connects producer and consumer *
**************************************************
public class InputStreamLender {
public static void lend(InputStreamProducer producer, InputStreamConsumer consumer)
throws Exception {
InputStream in = null;
try {
in = producer.produce();
consumer.consume(in);
} finally {
if (in != null) {
in.close();
}
}
}
}
**************************************************
Util class providing implementation for *
a InputstreamProvider *
**************************************************
public class InputStreamUtils {
public static InputStreamProducer fromClassPath(final String path) {
return new InputStreamProducer() {
@Override
public InputStream produce() throws Exception {
return InputStreamUtils.class.getClassLoader().getResourceAsStream(path);
}
};
}
}
**************************************************
Small test class testing we get indeed an *
inputstream to work with *
**************************************************
public class InputStreamLenderTest {
@Test
public void testInputStreamLender() throws Exception {
InputStreamLender.lend(
InputStreamUtils.fromClassPath("test.properties"),
new InputStreamConsumer() {
@Override
public void consume(InputStream in) throws Exception {
Assert.assertNotNull(in);
}
});
}
}
**************************************************
A class using our newly developed loan pattern *
**************************************************
public class PropertyLoader {
public static Properties loadFromClassPath(String path) throws Exception{
final Properties props = new Properties();
InputStreamLender.lend(
InputStreamUtils.fromClassPath(path),
new InputStreamConsumer() {
@Override
public void consume(InputStream in) throws Exception {
props.load(in);
}
});
return props;
}
}
**************************************************
view raw gistfile1.java hosted with ❤ by GitHub

2 comments:

  1. Nice pattern for Java6, but in Java7 handling streams is a lot easier if you use try-with-resources:

    try (InputStream in = producer.produce) {
    consumer.consume(in);
    }

    Since InputStream implements java.lang.Autocloseable you don't need to manually close the stream in a finally (which may fail).

    ReplyDelete
    Replies
    1. yes.. exactly... i read about those enhancements but i'm still using jdk1.6. Are you already using 1.7 in your projects nowadays? I delayed the switch at the time because 1.7 still had some issues as far as I remember

      Delete