Java IO Streams as Decorator Pattern
Fast recall
Quick revision
Core answer
Interview-ready guide
Interview answer
Java IO is built on Decorator pattern.
InputStream is the component interface—well, it's an abstract class, but it plays that role. Concrete streams like FileInputStream and ByteArrayInputStream are the base components. They just read raw bytes from a source.
Then FilterInputStream is the base decorator—it wraps another stream and delegates everything to it. Concrete decorators like BufferedInputStream, DataInputStream, and GZIPInputStream extend FilterInputStream and add specific behaviors. BufferedInputStream adds buffering so you're not hitting disk on every single byte read.
DataInputStream adds typed reading—methods like readInt or readDouble that handle the byte-to-number conversion for you. GZIPInputStream adds decompression. You stack them by nesting constructors: new BufferedReader, wrapping InputStreamReader, wrapping FileInputStream.
Each layer adds one capability. The file stream reads raw bytes, the input stream reader converts bytes to characters, the buffered reader adds buffering and line-by-line reading. That's Decorator in action.
One common mistake is not realizing this is a pattern. Freshers see the weird nested syntax and think it's just quirky API design. But it's deliberate—Decorator lets Java provide a small set of base streams and decorators that combine flexibly instead of having a giant class for every possible combination.
Another mistake is closing streams in the wrong order or closing each layer separately. You only close the outermost decorator, and it closes the entire chain automatically.
Java IO Streams as Decorator Pattern
Direct Answer
Java IO uses Decorator extensively: InputStream is the component interface, FileInputStream and ByteArrayInputStream are concrete components, and FilterInputStream is the base decorator. BufferedInputStream, DataInputStream, and others wrap streams to add buffering, typed reading, or compression without changing the underlying stream.
Code Example
import java.io.*;
public class StreamDecoratorDemo {
public void readFileWithDecorators(String filepath) throws IOException {
// Base component: reads raw bytes from file
InputStream fileStream = new FileInputStream(filepath);
// First decorator: adds buffering for performance
InputStream bufferedStream = new BufferedInputStream(fileStream);
// Second decorator: adds typed reading (readInt, readDouble)
DataInputStream dataStream = new DataInputStream(bufferedStream);
// Each decorator wraps the previous, adding behavior
int value = dataStream.readInt(); // Buffered, typed read from file
dataStream.close(); // Closes entire decorator chain
}
public void alternativeChain(String filepath) throws IOException {
// Common idiom: nest constructors to build decorator stack
try (var reader = new BufferedReader(
new InputStreamReader(
new FileInputStream(filepath)))) {
String line = reader.readLine(); // Buffered, character-decoded read
System.out.println(line);
} // try-with-resources closes all layers
}
}
Common Mistakes & Pitfalls
- Not closing the outermost stream: Freshers close the FileInputStream directly, thinking they need to close each layer—but closing the outermost decorator (like DataInputStream) automatically closes the entire chain, and closing inner streams first can cause issues.
- Wrapping in wrong order: Wrapping BufferedInputStream inside DataInputStream instead of outside—the buffering layer should be closest to the raw source so DataInputStream reads from the buffer, not from disk repeatedly.
- Not recognizing the pattern: Treating Java IO as random classes with weird nesting syntax—missing that it's Decorator in action helps you understand why the API is designed this way and how to build custom stream decorators when needed.
Check your understanding
Answer these without looking back at the article.
- How would you implement a LoggingInputStream decorator?
- What would an EncryptingOutputStream look like?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.