Design Patterns «Prev Next»

Lesson 5Why use design patterns?
ObjectiveUnderstand how design patterns improve design quality, speed delivery, and make systems easier to change.

Design Pattern Benefits and How They Assist Programmers

Design patterns are named, proven arrangements of roles and collaborations that solve recurring design problems. They accelerate communication (“use Strategy here”), reduce coupling, and create clear seams for testing and change. They are not silver bullets-but when applied deliberately, they shorten time-to-first-feature and lower long-term maintenance cost.

What Patterns Do and Don’t Do

Where Patterns Help in the Software Lifecycle

PhaseHow Patterns HelpTypical Deliverables
Analysis Turn vague “variability points” into candidate roles (Policy, Strategy, Observer, Adapter). Context diagrams, responsibility notes, candidate role list.
Design Choose patterns to isolate construction, behavior changes, and collaboration. Class/sequence sketches, interface contracts, trade-off notes.
Implementation Faster coding using known layouts (factories, decorators, mediators). Interfaces + small classes with clear responsibilities.
Testing Mock collaborators behind interfaces; test policies in isolation. Unit tests per role; contract tests for shared interfaces.
Documentation Concise explanations using pattern names instead of pages of prose. “We use Observer for events; Strategy for pricing” in README/design notes.

Concrete Benefits

  1. Faster design & coding: You start from a tested arrangement rather than inventing one.
  2. Reduced coupling: Roles communicate via interfaces, enabling safe substitution.
  3. Testability: Policies and collaborators are injectable and mockable.
  4. Consistency & onboarding: New teammates recognize familiar structures.
  5. Change tolerance: Requirements evolve; well-placed patterns confine edits to a few classes.
  6. Reusability: Composition and delegation (not inheritance alone) enable reuse across contexts.
  7. Communication: Pattern names compress complex designs into a few words.

Mini Examples

Java - Strategy to vary business rules without branching:

Place each public type in its own source file and import java.math.BigDecimal.

import java.math.BigDecimal;

public interface PriceRule { BigDecimal apply(BigDecimal base); }

public final class HolidayDiscount implements PriceRule {
  public BigDecimal apply(BigDecimal base) { return base.multiply(new BigDecimal("0.90")); }
}

public final class NoDiscount implements PriceRule {
  public BigDecimal apply(BigDecimal base) { return base; }
}

public final class CheckoutService {
  private final PriceRule rule; // injected (composition over inheritance)
  public CheckoutService(PriceRule rule) { this.rule = rule; }
  public BigDecimal total(BigDecimal subtotal) { return rule.apply(subtotal); }
}
// Swap policies at runtime: new CheckoutService(new HolidayDiscount())

Java - Factory Method to defer concrete selection:

The following self-contained sketch uses strings so the creation hook remains the focus:

interface Storage extends AutoCloseable {
  String fetch(String id);
  void close();
}

abstract class ImageStore {
  public final String load(String id) {
    Storage s = open();       // factory method
    try { return s.fetch(id); }
    finally { s.close(); }
  }
  protected abstract Storage open();
}

class S3ImageStore extends ImageStore {
  protected Storage open() {
    return new Storage() {
      public String fetch(String id) { return "s3://" + id; }
      public void close() { }
    };
  }
}

When Not to Use a Pattern

Adoption Checklist

Design Patterns Purpose - Quiz

Test your understanding with a short quiz:
Design Patterns Purpose - Quiz

[1]Delegation: One object exposes an operation but forwards work to another object that owns the behavior.
[2]Composition: Building objects from other objects (has-a) rather than using inheritance (is-a).

SEMrush Software 5 SEMrush Banner 5