May 21, 2013

Java I/O -- the Decorator and proxy design pattern interview questions and answers

Q. Can you explain the decorator design pattern?
A. By implementing the decorator pattern you construct a wrapper around an object by extending its behavior. The wrapper will do its job before or after and delegate the call to the wrapped instance. The decoration happens at run-time. In Java, the wrapper classes like Integer, Double, etc are typical example of a decorator pattern. Another good example is the Java I/O classes as shown below. Each reader or writer will decorate the other to extend or modify the behavior.

String inputText = "Some text to read";
ByteArrayInputStream bais = new ByteArrayInputStream(inputText.getBytes());
Reader isr = new InputStreamReader(bais);
BufferedReader br = new BufferedReader(isr);

As you can see, each reader extends the behavior at run-time. This is the power of object composition as opposed to inheritance. By composing a fewer classes at run-time, desired behavior can be created. Here is another example demonstrating an interleaved reading using a class from the Apache library.


class InterleavedReadingFromFile {
    public static void main(String[] args) throws IOException {

        // Create the source input stream.
        InputStream is = new FileInputStream("c:\temp\persons.txt");

        // Create a piped input stream for one of the readers.
        PipedInputStream in = new PipedInputStream();

        // Create a tee-splitter for the other reader. This is from the Apache library
        TeeInputStream tee = new TeeInputStream(is, new PipedOutputStream(in));

        // Create the two buffered readers.
        BufferedReader br1 = new BufferedReader(new InputStreamReader(tee));
        BufferedReader br2 = new BufferedReader(new InputStreamReader(in));

        // You can now do interleaved reads
        System.out.println("1 line from br1");

        System.out.println("2 lines from br2:");

        System.out.println("1 line again from br1:");

Q. Can you write a class using the decorator design pattern to print numbers from 1-10, and then decorators that optionally print only even or odd numbers?
A. Java decorator pattern

Q. How does a decorator design pattern differ from a proxy design pattern?
A. In Proxy pattern, you have a proxy and a real subject. The relationship between a proxy and the real subject is typically set at compile time, whereas decorators can be recursively constructed at run time. The Decorator Pattern is also known as the Wrapper pattern. The Proxy Pattern is also known as the Surrogate pattern. The purpose of decorator pattern is to add additional responsibilities to an object. These responsibilities can of course be added through inheritance, but composition provides better flexibility as explained above via the Java I/O classes. The purpose of the proxy pattern is to add an intermediate between the client and the target object. This intermediate shares the same interface as the target object. Here are some scenarios in which a proxy pattern can be applied.

  • A remote proxy provides a local representative for an object in a different address space.Providing interface for remote resources such as web service or REST resources or EJB using RMI.
  • A virtual proxy creates expensive object on demand.
  • A protection proxy controls access to the original object.Protection proxies are useful when objects should have different access rights.
  • A smart reference is a replacement for a bare pointer that performs additional actions when an object is accessed.
  • Adding a thread-safe feature to an existing class without changing the existing class's code. This is useful when you do not have the freedom to fix thread-safety issues in a third-party library.
The proxy design pattern is explained with a dynamic proxy class to gather performance results in the blog entitled  Java Interview Questions and Answers - performance testing your Java application.

Q. Can you list some of the best practices relating to Java I/O
  1. As demonstrated in Java I/O interview Questions, it is a good practice to close all instances of in a finally block.
  2. Use BufferedReader and BufferedWriter to increase efficiency because IO performance depends a lot from the buffering strategy. 
  3. Favor NIO over old IO because the old I/O is stream oriented and uses a blocking IO, whereas the NIO (aka New IO) is Buffer oriented, uses Non blocking I/O and has selectors. 
  4. To avoid issues like "the file reading works in Windows but not in Unix", use constructors instead of working with file names as String. The FilenameUtils class in Apache. commons IO handles issues relating to operating systems. 
  5. Apache FileUtils class is  very handy for touching, copying, moving, deleting, calculating the checksum, calculating last modified date, listing and filtering directories, comparing file content, etc.

Other design patterns - real life examples

Labels: ,


Post a Comment

Subscribe to Post Comments [Atom]

<< Home