Design Patterns

Compound Patterns & MVC

Real designs rarely use one pattern in isolation — they combine several to solve a larger problem. Model-View-Controller is the most widely recognized compound pattern: Observer, Strategy, and Composite working together.
  • A compound pattern is a combination of two or more patterns applied together to address a recurring higher-level design problem
  • MVC decomposes an application into Model (state and business logic), View (presentation), and Controller (translates user input into model changes)
  • MVC is Observer (the View observes the Model for changes) + Strategy (the Controller is a swappable strategy for handling input) + Composite (the View is typically a tree of nested UI components)
  • The Model has no knowledge of any specific View — multiple Views can observe the same Model simultaneously and stay in sync automatically
  • Modern variants (MVP, MVVM, unidirectional-data-flow architectures) are all descendants of the same core idea: separate what changes (state), how it's shown, and how input is handled
MVC decomposed into the patterns it's built from
MVC partResponsibilityPattern used
Modelstate + business rules; notifies on changeObserver (subject side)
Viewrenders the model; often a nested UI treeObserver (observer side) + Composite
Controllerinterprets input, updates the ModelStrategy (swappable input-handling behavior)
MVC sketch — the Model knows nothing about any View
interface ModelListener { void onChange(); }

class TemperatureModel {
    private double celsius;
    private final List<ModelListener> listeners = new ArrayList<>();

    void addListener(ModelListener l) { listeners.add(l); }
    void setCelsius(double c) {
        this.celsius = c;
        listeners.forEach(ModelListener::onChange);   // Observer: notify every registered View
    }
    double getCelsius() { return celsius; }
}

class TemperatureView implements ModelListener {
    private final TemperatureModel model;
    TemperatureView(TemperatureModel model) { this.model = model; model.addListener(this); }
    public void onChange() { System.out.println(model.getCelsius() + "°C"); }   // render current state
}

class TemperatureController {
    private final TemperatureModel model;
    TemperatureController(TemperatureModel model) { this.model = model; }
    void userEnteredFahrenheit(double f) { model.setCelsius((f - 32) * 5 / 9); }   // input -> Model change
}
Sources
  • Head First Design Patterns (2nd ed.)Ch. 12 — Compound Patterns (MVC)