Reference
Java Stdlib Map
Every GoF pattern in the JDK — real class and method references you already use.
01
Introduction
Why This Matters
Every pattern in this course already exists in code you use daily. The Java standard library is a masterclass in design patterns — the JDK authors applied these patterns decades before you learned their names. Knowing where each pattern lives in the JDK gives you:
- Instant credibility in interviews — citing a real JDK example proves you understand the pattern beyond textbook definitions
- Better API intuition — when you recognise the pattern behind an API, you predict its behaviour without reading docs
- Design confidence — if the JDK uses this pattern for
Iterator, it’s good enough for your codebase too
How to read this page: Each table below maps a pattern to its JDK location, with the specific class, method, and the role it plays in the pattern. The code examples section shows the pattern in action with real stdlib calls — not reimplementations.
02
Creational Patterns
Creational — JDK Locations
| Pattern | JDK Class / Method | Role in Pattern |
|---|---|---|
| Singleton | java.lang.Runtime.getRuntime() | Single JVM runtime instance; private constructor, static accessor |
java.awt.Desktop.getDesktop() | One desktop integration point per JVM | |
| Factory Method | java.util.Calendar.getInstance() | Returns GregorianCalendar or JapaneseImperialCalendar based on locale |
java.nio.charset.Charset.forName() | Returns platform-specific Charset subclass | |
java.util.Collection.iterator() | Each collection returns its own concrete Iterator (textbook FM) | |
| Abstract Factory | javax.xml.parsers.DocumentBuilderFactory | Factory of factories — creates a DocumentBuilder without naming the implementation |
java.sql.DriverManager.getConnection() | Returns a Connection from the appropriate driver (family of DB objects) | |
| Builder | java.lang.StringBuilder | Step-by-step string construction: .append().append().toString() |
java.util.stream.Stream.Builder | Build a Stream element by element: .add().add().build() | |
java.net.http.HttpRequest.newBuilder() | Fluent builder: .uri().header().GET().build() (Java 11+) | |
| Prototype | java.lang.Object.clone() | Clone existing object instead of constructing from scratch |
new ArrayList<>(existingList) | Copy constructor — modern alternative to clone() |
03
Structural Patterns
Structural — JDK Locations
| Pattern | JDK Class / Method | Role in Pattern |
|---|---|---|
| Adapter | java.util.Arrays.asList(T[]) | Adapts an array to the List interface |
java.io.InputStreamReader(InputStream) | Adapts byte stream (InputStream) to character stream (Reader) | |
| Bridge | java.util.logging (Logger + Handler) | Logger (abstraction) delegates to Handler (implementation) — both vary independently |
| Composite | java.awt.Container | Container holds Components (which may be other Containers) — uniform tree |
javax.faces.component.UIComponent | JSF component tree with leaf & composite nodes | |
| Decorator | java.io.BufferedReader(Reader) | Adds buffering to any Reader — same interface, extra behaviour |
java.io.DataInputStream(InputStream) | Adds typed-read methods (readInt(), readUTF()) to raw byte stream | |
Collections.unmodifiableList(List) | Wraps a List, adds immutability constraint — Decorator that restricts rather than adds | |
| Facade | java.net.URL | Hides socket/protocol/DNS complexity behind openStream() |
javax.faces.context.FacesContext | Single entry point to request, response, session, application | |
| Flyweight | java.lang.Integer.valueOf(int) | Caches Integer objects for -128 to 127 — shared immutable instances |
java.lang.String.intern() | Returns canonical instance from the string pool | |
| Proxy | java.lang.reflect.Proxy | Dynamic proxy — generates interface implementations at runtime |
java.rmi.* stubs | Remote proxy — forwards calls over the network |
04
Behavioral Patterns
Behavioral — JDK Locations
| Pattern | JDK Class / Method | Role in Pattern |
|---|---|---|
| Observer | java.beans.PropertyChangeListener | Observer interface; PropertyChangeSupport is the subject |
java.util.EventListener | Marker interface for all Swing/AWT event observers | |
java.util.concurrent.Flow (Java 9+) | Reactive Streams: Publisher, Subscriber, Subscription | |
| Strategy | java.util.Comparator | Swappable comparison algorithm for sorting |
java.util.Collections.sort(list, comparator) | Context that accepts and uses the strategy | |
| Command | java.lang.Runnable | Encapsulates an action with no return value |
java.util.concurrent.Callable<V> | Command with a return value, can throw exceptions | |
javax.swing.Action | Reusable command for toolbar buttons, menus, and keyboard shortcuts | |
| Template Method | java.util.AbstractList | Defines get() and size() as hooks; indexOf(), iterator() are the template methods |
java.io.InputStream.read(byte[], int, int) | Multi-byte read calls the abstract single-byte read() in a loop | |
| Chain of Resp. | javax.servlet.Filter | HTTP filter chain — each filter processes or passes the request along |
java.util.logging.Logger | Logger hierarchy passes log records up the parent chain | |
| State | javax.faces.lifecycle.LifeCycle | JSF request phases as state transitions |
java.util.Iterator | Internal state determines hasNext()/next() behaviour | |
| Mediator | java.util.concurrent.Executor | Mediates between task submission and thread execution |
javax.swing.ButtonGroup | Ensures only one button in the group is selected — buttons don’t know about each other | |
| Iterator | java.util.Iterator<E> | Traverse any collection without exposing internals |
java.util.Spliterator<E> | Parallel-aware iterator for Stream API | |
| Visitor | java.nio.file.FileVisitor<Path> | Visit files/directories without modifying the file tree classes |
javax.lang.model.element.AnnotationValueVisitor | AST visitor for annotation processing at compile time | |
| Memento | java.io.Serializable | Snapshot/restore object state via serialization |
java.util.Date (get/setTime) | Internal long timestamp acts as a memento of the date state |
Deprecated:
java.util.Observable and java.util.Observer were deprecated in Java 9. Use java.beans.PropertyChangeListener or the java.util.concurrent.Flow API (reactive streams) instead.
05
Code Examples
Stdlib Usage Examples
Each example below shows a real JDK pattern in action — not a reimplementation, but actual stdlib usage. Use these as interview talking points.
Singleton —
Runtime.getRuntime() Runtime rt = Runtime.getRuntime();
System.out.println("Processors: " + rt.availableProcessors());
System.out.println("Max memory: " + rt.maxMemory() / 1024 / 1024 + " MB");
// Always the same instance โ private constructor, static accessor
System.out.println(rt == Runtime.getRuntime()); // true
Factory Method —
Collection.iterator() // Each collection returns its own concrete Iterator โ textbook Factory Method List<String> list = List.of("A", "B", "C");
Set<String> set = Set.of("X", "Y", "Z");
Iterator<String> listIter = list.iterator(); // ArrayList$Itr Iterator<String> setIter = set.iterator(); // ImmutableCollections$SetN$SetNIterator // Caller only touches Iterator<E> โ never the concrete class while (listIter.hasNext()) System.out.print(listIter.next() + " ");
Builder —
HttpRequest.newBuilder() // Java 11+ HTTP Client โ fluent Builder pattern HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/orders"))
.header("Accept", "application/json")
.header("Authorization", "Bearer token123")
.GET()
.build();
// Step-by-step construction, immutable result, clear API
Adapter —
Arrays.asList() String[] arr = {"alpha", "beta", "gamma"};
// Adapts array (fixed-size, no List API) to List interface List<String> adapted = Arrays.asList(arr);
System.out.println(adapted.get(1)); // "beta" โ List API on an array!
System.out.println(adapted.size()); // 3 // adapted.add("delta"); // throws UnsupportedOperationException (fixed-size adapter)
Decorator —
java.io stream wrappers // Classic Decorator chain โ each wrapper adds behaviour InputStream raw = new FileInputStream("data.bin"); // base InputStream buf = new BufferedInputStream(raw); // + buffering DataInputStream data = new DataInputStream(buf); // + typed reads int version = data.readInt(); // reads 4 bytes as int String name = data.readUTF(); // reads length-prefixed UTF string // Same InputStream interface at every layer โ pure Decorator
Strategy —
Comparator List<String> names = List.of("Charlie", "Alice", "Bob");
// Swap sorting strategy at runtime โ textbook Strategy pattern List<String> byNatural = names.stream().sorted(Comparator.naturalOrder()).toList();
List<String> byLength = names.stream().sorted(Comparator.comparingInt(String::length)).toList();
List<String> byReverse = names.stream().sorted(Comparator.reverseOrder()).toList();
System.out.println(byNatural); // [Alice, Bob, Charlie]
System.out.println(byLength); // [Bob, Alice, Charlie]
System.out.println(byReverse); // [Charlie, Bob, Alice]
Observer —
PropertyChangeListener import java.beans.*;
class Account {
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private double balance;
public void addListener(PropertyChangeListener l) { pcs.addPropertyChangeListener(l); }
public void deposit(double amount) {
double old = balance;
balance += amount;
pcs.firePropertyChange("balance", old, balance); // notify all observers
}
}
// Usage: Account acct = new Account();
acct.addListener(evt -> System.out.println("Balance changed: " + evt.getNewValue()));
acct.deposit(100.0); // prints: Balance changed: 100.0
Flyweight —
Integer.valueOf() // Integer caches instances for -128 to 127 โ Flyweight pool Integer a = Integer.valueOf(42);
Integer b = Integer.valueOf(42);
System.out.println(a == b); // true โ same cached instance Integer x = Integer.valueOf(200);
Integer y = Integer.valueOf(200);
System.out.println(x == y); // false โ outside cache range // This is why `==` on Integer can be unreliable โ it depends on the Flyweight cache!
Chain of Responsibility —
javax.servlet.Filter // Servlet Filter chain โ each filter processes or passes the request public class AuthFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws ... {
if (isAuthenticated(req)) {
chain.doFilter(req, res); // pass to next handler
} else {
res.sendError(401); // handle here, don't pass
}
}
}
// Chain: AuthFilter โ LoggingFilter โ RateLimitFilter โ Servlet
Visitor —
FileVisitor<Path> // Walk a file tree โ add operations without modifying the tree classes Files.walkFileTree(Path.of("/src"), new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
if (file.toString().endsWith(".java")) {
System.out.println("Found: " + file);
}
return FileVisitResult.CONTINUE;
}
});
// New operation (count lines, find TODO, etc.) = new Visitor, zero edits to Path/File
Iterator —
Iterator<E> + enhanced for-loop // Any Iterable works in for-each โ Iterator pattern is built into the language Deque<String> stack = new ArrayDeque<>();
stack.push("first");
stack.push("second");
stack.push("third");
// Enhanced for-loop calls iterator() under the hood for (String item : stack) {
System.out.println(item); // third, second, first (LIFO order)
}
// Client doesn't know if it's a Deque, List, or Set โ just Iterable
Interview tip: When asked “Give a real-world example of [Pattern]”, cite the JDK class from this page. It’s more impressive than a textbook “Shape and Circle” example because it shows you’ve actually worked with the pattern in production code.