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.