Lesson Completion
Back to course

Structural Patterns Part 2: Bridge, Composite, and Flyweight

Beginner
12 minutes4.7Java

1. The Hook (The "Byte-Sized" Intro)

  • In a Nutshell: Bridge = decouple abstraction from implementation (remote control + device), Composite = tree structure, treat leaf & composite uniformly (file system: files + folders), Flyweight = share objects to save memory (String pool, chess pieces).
  • Benefits: Flexibility (Bridge), uniform treatment (Composite), memory efficiency (Flyweight).
  • Use: Bridge for platform independence, Composite for part-whole hierarchies, Flyweight for many similar objects!

Bridge = universal remote (one remote, many devices). Composite = company org chart (CEO → managers → employees, all are "Employee"). Flyweight = concert tickets (shared venue info, unique seat number)!


2. Conceptual Clarity (The "Simple" Tier)

💡 The Analogy

  • Bridge: Car + driver (separate concerns)
  • Composite: Russian nesting dolls (container + items)
  • Flyweight: Library books (share content, unique borrower card)

3. Technical Mastery (The "Deep Dive")

java
// =========================================== // 1. BRIDGE PATTERN // =========================================== // Implementation interface Device { void turnOn(); void turnOff(); } class TV implements Device { public void turnOn() { System.out.println("TV on"); } public void turnOff() { System.out.println("TV off"); } } class Radio implements Device { public void turnOn() { System.out.println("Radio on"); } public void turnOff() { System.out.println("Radio off"); } } // Abstraction abstract class RemoteControl { protected Device device; RemoteControl(Device device) { this.device = device; } abstract void togglePower(); } class BasicRemote extends RemoteControl { BasicRemote(Device device) { super(device); } void togglePower() { device.turnOn(); device.turnOff(); } } // Usage: Mix and match! RemoteControl remote1 = new BasicRemote(new TV()); RemoteControl remote2 = new BasicRemote(new Radio()); // =========================================== // 2. COMPOSITE PATTERN // =========================================== // Component interface FileSystemNode { void print(String indent); int getSize(); } // Leaf class File implements FileSystemNode { private String name; private int size; File(String name, int size) { this.name = name; this.size = size; } public void print(String indent) { System.out.println(indent + name + " (" + size + " bytes)"); } public int getSize() { return size; } } // Composite class Folder implements FileSystemNode { private String name; private List<FileSystemNode> children = new ArrayList<>(); Folder(String name) { this.name = name; } void add(FileSystemNode node) { children.add(node); } public void print(String indent) { System.out.println(indent + name + "/"); for (FileSystemNode child : children) { child.print(indent + " "); } } public int getSize() { return children.stream() .mapToInt(FileSystemNode::getSize) .sum(); } } // Usage: Folder root = new Folder("root"); root.add(new File("file1.txt", 100)); Folder docs = new Folder("docs"); docs.add(new File("doc1.pdf", 500)); docs.add(new File("doc2.pdf", 300)); root.add(docs); root.print(""); // Prints tree structure System.out.println("Total: " + root.getSize()); // =========================================== // 3. FLYWEIGHT PATTERN // =========================================== // Flyweight (intrinsic state = shared) class ChessPiece { private final String color; // Shared private final String type; // Shared ChessPiece(String color, String type) { this.color = color; this.type = type; } void render(int x, int y) { // Extrinsic state = unique System.out.println(color + " " + type + " at (" + x + "," + y + ")"); } } // Flyweight factory class ChessPieceFactory { private static Map<String, ChessPiece> pieces = new HashMap<>(); static ChessPiece getPiece(String color, String type) { String key = color + "-" + type; if (!pieces.containsKey(key)) { pieces.put(key, new ChessPiece(color, type)); System.out.println("Created: " + key); } return pieces.get(key); } } // Usage: ChessPiece p1 = ChessPieceFactory.getPiece("White", "Pawn"); ChessPiece p2 = ChessPieceFactory.getPiece("White", "Pawn"); // p1 == p2 (same object!) p1.render(0, 1); p2.render(1, 1); // Shared object, different positions!

5. The Comparison & Decision Layer

PatternUse When
BridgeVary abstraction + implementation independently
CompositePart-whole hierarchy, tree structure
FlyweightMany similar objects, memory optimization

6. The "Interview Corner" (The Edge)

The "Killer" Interview Question: "Explain Flyweight with String pool." Answer: String pool is Flyweight pattern!

java
String s1 = "Hello"; // Created in pool String s2 = "Hello"; // Reuses same object! System.out.println(s1 == s2); // true (same reference) // Flyweight: // - Intrinsic state: "Hello" (shared) // - Extrinsic state: Where it's used (unique) // - Factory: String pool

Pro-Tip: Composite in UI frameworks:

java
// Swing uses Composite JPanel panel = new JPanel(); // Composite panel.add(new JButton("OK")); // Leaf panel.add(new JLabel("Name")); // Leaf JPanel nested = new JPanel(); // Another composite nested.add(new JTextField()); panel.add(nested); // Composite in composite! // All are Component (uniform interface)

Topics Covered

Java Fundamentals

Tags

#java#programming#beginner-friendly

Last Updated

2025-02-01