CMD Guide
HomeOO & Low-Level Design

Design Patterns Overview

Step 3 in the OO & Low-Level Design path · 9 concepts · 0 problems

0 / 9 complete

📘 Learn Design Patterns Overview from zero

What design patterns are. A design pattern is a named, reusable solution to a recurring object-oriented design problem — not a finished library or a snippet you paste, but a template for how classes and objects collaborate. The canonical source is the Gang of Four (GoF) book, Design Patterns: Elements of Reusable Object-Oriented Software, which documents 23 patterns. Each is described by four essentials: name (shared vocabulary), problem/intent (when to apply it), solution (the participating classes and their responsibilities), and consequences (the trade-offs you accept).

Why they matter at FAANG level. Patterns are a compression of design intent. Saying "use a Strategy here" conveys structure, extension points, and trade-offs in one word. In low-level design interviews they signal that you reach for vetted structure instead of reinventing — and, just as important, that you know when not to (premature patterning is a red flag).

Classification of design patterns. GoF classifies along two dimensions. By purpose: Creational (object creation — Factory Method, Abstract Factory, Builder, Prototype, Singleton), Structural (composition of classes/objects — Adapter, Bridge, Composite, Decorator, Facade, Flyweight, Proxy), and Behavioral (responsibility and communication — Strategy, State, Observer, Command, Template Method, Iterator, and others). By scope: class patterns (fixed at compile time via inheritance) versus object patterns (composed and changeable at runtime). The two principles underlying nearly all of them: program to an interface, not an implementation, and favor object composition over class inheritance.

✨ Added by the guide to build intuition — not from the source course.

🎯 Guided practice

  1. Easy — classify, and correctly distinguish Simple Factory from GoF Factory Method. Problem: a logging library must produce a Logger that could be FileLogger or ConsoleLogger, chosen by config. Reasoning: (1) Spot the smell — callers do new FileLogger(), so adding a logger type touches every caller. This is an object-creation problem, so look in the creational family. (2) The straightforward fix is a LoggerFactory.create(config) with a switch returning the Logger interface. Name it correctly: a single method that branches on a parameter is the Simple Factory idiom (not a GoF pattern). (3) The true GoF Factory Method is different: a base class declares an abstract createLogger() and subclasses decide the concrete product — e.g. FileLogManager overrides it to return a FileLogger. The decision moves to polymorphism, not a branch. (4) Either way callers depend only on Logger, so adding NetworkLogger is localized. Takeaway: Simple Factory = one method picks the product by parameter; Factory Method = an overridable method lets a subclass pick. Interviewers probe this exact confusion.
  2. Medium — Strategy vs State (pick the right behavioral pattern). Problem: a media player has Play, Pause, Stop. Button behavior depends on the current mode, and pressing a button moves the player to a new mode (Playing then Paused). Reasoning: (1) Behavior varies by a "mode" field with a big switch — behavioral family. (2) Ask the discriminating question: does the caller pick the behavior, or does the object transition itself? Pressing Play in Stopped mode moves the player to Playing — the object drives its own transitions. That is State, not Strategy. (3) Model each mode as a class implementing PlayerState with play()/pause()/stop(); each method performs the action and sets the next state via player.setState(...). (4) Contrast: if the user instead freely chose a compression algorithm with no transition rules, that is Strategy — caller selects, object does not self-mutate. Takeaway: Strategy = interchangeable algorithms chosen externally; State = an encapsulated mode that manages its own transitions. Near-identical structure (interface plus concrete classes), opposite intent.
  3. Hard — Decorator vs subclassing (structural, runtime composition). Problem: a coffee-shop ordering system has a Beverage with a base cost, and any drink can add milk, soy, mocha, or whip in any combination, each adding cost. Reasoning: (1) The naive fix is a subclass per combination (DarkRoastWithMochaAndWhip), which explodes combinatorially — a class-inheritance smell, so reach for a structural pattern. (2) Apply favor composition over inheritance: a CondimentDecorator implements the same Beverage interface and wraps a Beverage, delegating cost() to the wrapped object and adding its own. (3) new Whip(new Mocha(new DarkRoast())) composes behavior at runtime; each decorator preserves the Beverage interface so the client never knows it is holding a wrapped object. (4) Why not Adapter? Adapter changes an interface to make a fixed class usable; Decorator keeps the same interface and adds responsibility. Why not Strategy? Strategy swaps one pluggable algorithm; Decorator stacks many layers. Takeaway: Decorator = open for extension, closed for modification — add behavior by wrapping at runtime instead of subclassing every combination. This is the canonical Head First example of the Open/Closed Principle.

✨ Added by the guide — work these before the full problem set.

Lessons in this topic

🧠 Review & recall

Active recall is what moves a topic into long-term memory. Flip each card before revealing, then test yourself — your results are saved on this device.

Flashcard
What is a design pattern, and what is it NOT?
tap to reveal →
A design pattern is a typical, reusable solution to a recurring software-design problem — a customizable template or guideline distilled from many developers' experience. It is NOT ready-made code you paste in; you adapt it to your specific requirements.
💡 Template, not paste — a blueprint for door placement, not a pre-built door.
Flashcard
What are the three GoF categories of design patterns and what does each address?
tap to reveal →
Creational (object-creation mechanisms, keeping the system flexible and decoupled from concrete types), Structural (how classes/objects compose into larger structures and relationships), and Behavioral (algorithms and assignment of responsibilities/communication between objects).
💡 CSB: Create it, Structure it, Behave with it.
Flashcard
Name the five creational patterns covered and the one-line distinctive feature of each.
tap to reveal →
Singleton (ensures only one instance exists with global access), Factory Method (defines a creation interface where subclasses decide the type), Abstract Factory (creates families of related objects without concrete classes), Builder (separates construction of a complex object from its representation, step by step), and Prototype (creates new objects by copying an existing one).
💡 'SFABP' — one, subclass-picks, family, step-by-step, clone.
Flashcard
According to the Decorator summary, when do you use it and what is its main advantage over subclassing?
tap to reveal →
Use Decorator to add responsibilities to objects dynamically at runtime (e.g. adding scrolling to a text view). Its advantage: more flexible than subclassing and avoids feature-loaded classes; its con is that it can lead to complex, hard-to-debug code structure.
💡 Wrap to add at runtime instead of subclassing every combo.
Flashcard
What is the discriminating difference between Strategy and State (both behavioral)?
tap to reveal →
Strategy enables an algorithm's behavior to be selected at runtime by the client (e.g. different compression algorithms) — the client chooses. State lets an object alter its behavior when its internal state changes (e.g. game modes) — the object transitions itself. Near-identical structure, opposite intent.
💡 Strategy = you pick the algorithm; State = the object changes its own mode.
Flashcard
What does the Proxy pattern do, and what are typical use cases from the summary?
tap to reveal →
Proxy provides a placeholder for another object to control access to it. Typical uses: lazy loading, logging, access control, and smart reference (e.g. an internet proxy server controlling web access). Pro: controls access and reduces cost of expensive operations; con: adds indirection that may impact performance.
💡 Stand-in gatekeeper: lazy-load, log, restrict, reference.
Q1. A team needs to create GUI elements that stay compatible within a chosen OS theme (e.g. all Windows-style or all macOS-style widgets) without naming concrete classes. Which creational pattern fits best?
Q2. Which statement about design patterns is correct per the lessons?
Q3. You must give clients one standard way to traverse a playlist's elements sequentially without exposing how the collection is stored internally. Which behavioral pattern applies?
Q4. A document system must support creating PDF, Word, and other types via a common Document class, with the concrete type decided by subclasses. Which pattern matches, and what is a noted drawback?
Q5. Which pattern minimizes memory usage by sharing as much data as possible among large numbers of similar objects (e.g. characters in a word processor)?