Design Patterns Coupling and Cohesion

Coupling and cohesion measure the health of a design. Links between classes define coupling, which grows tighter as dependencies deepen. Cohesion describes how closely the pieces inside one class belong together. Strong designs show low coupling and high cohesion, and nearly every pattern pushes code toward that goal.

The Layman's View

Think of a toolbox. A well-organized box keeps screwdrivers in one tray and drills in another. Every tray holds related tools, which means high cohesion. A lamp wired straight into the wall needs an electrician for every bulb change, which means high coupling. Swapping parts on a plug-and-socket lamp takes seconds, which means low coupling.

Understanding Coupling

Two classes are tightly coupled when one cannot work without knowing the inner details of the other. A change in one class forces a change in the second.

TIGHT COUPLING                      LOOSE COUPLING

 ┌──────────┐   knows all   ┌────────────┐      ┌──────────┐   ┌───────────┐   ┌────────────┐
 │ Checkout │ ────────────▶ │ CardPayment│      │ Checkout │──▶│ Payment   │◀──│ CardPayment│
 └──────────┘   details     └────────────┘      └──────────┘   │(interface)│   └────────────┘
                                                               └───────────┘
 Change CardPayment → Checkout breaks         Change CardPayment → Checkout stays safe

Levels of Coupling

  • Tight: a class creates another class directly with the new keyword.
  • Moderate: a class receives a concrete object from outside.
  • Loose: a class talks to an interface and knows nothing about the real type.

Understanding Cohesion

A cohesive class has one clear purpose, and every method supports it. An Invoice class that calculates totals, applies tax, and formats line items stays cohesive. The same class with email sending and file compression mixed in loses focus.

HIGH COHESION                      LOW COHESION

┌───────────────────┐              ┌───────────────────┐
│ Invoice           │              │ Utility           │
│ addItem()         │              │ calculateTax()    │
│ calculateTotal()  │              │ sendEmail()       │
│ applyTax()        │              │ compressFile()    │
└───────────────────┘              │ parseDate()       │
                                   └───────────────────┘

Why Low Coupling and High Cohesion Matter

BenefitExplanation
Easier changesAn edit stays inside one class instead of spreading across ten.
Simpler testingLoose parts accept fake objects during tests.
Better reuseA focused class moves into another project with little effort.
Faster readingNew teammates grasp a class that does one thing.

Code Example: Reducing Coupling

// Tight coupling
class Checkout {
    private CardPayment payment = new CardPayment();   // locked to one type
    void pay(double amount) { payment.charge(amount); }
}

// Loose coupling
interface Payment { void charge(double amount); }

class Checkout {
    private Payment payment;
    Checkout(Payment payment) { this.payment = payment; }   // any Payment works
    void pay(double amount) { payment.charge(amount); }
}

The second version accepts card, wallet, or voucher payments without a single edit to Checkout.

Patterns That Lower Coupling

  • Observer lets a subject notify listeners without knowing who they are.
  • Mediator routes messages through one hub, and peers never talk directly.
  • Factory Method hides which concrete class gets created.
  • Facade shields clients from a crowd of subsystem classes.

Patterns That Raise Cohesion

  • Strategy moves each algorithm into its own focused class.
  • Command packs one action into one object.
  • Builder separates construction steps from the finished product.

Quick Self-Check

Ask three questions about any class. Does one sentence describe its purpose? Can you test it without starting the whole application? Does a change elsewhere force edits inside it? Two "no" answers suggest a redesign.

Measuring the Two Qualities

No ruler measures coupling, but a few habits give a useful estimate. Count how many other classes a class must import. Large counts suggest tight coupling. Count how many unrelated tasks a class performs. Large counts suggest weak cohesion.

A Small Exercise

Open any class from your project and list its methods on paper. Group methods that use the same data. Two or three clear groups reveal hidden classes waiting to be separated. Extract one group into a new class and check whether the original class reads more clearly.

Balance in Practice

Extreme loose coupling creates a maze of tiny interfaces that nobody can follow. Moderate goals work better: aim for modules that a teammate can describe in one sentence and replace without a rewrite.

Key Takeaways

  • Coupling measures how much classes depend on each other, and lower is better.
  • Cohesion measures how well a class stays focused, and higher is better.
  • Interfaces and composition cut coupling.
  • Patterns offer proven shapes that reach both goals.