# Encapsulation

> Hide internal state behind controlled access — expose methods, not fields, so nothing outside the class can corrupt the object's integrity.

- **Category**: Oop Concepts
- **Subcategory**: principles
- **Canonical URL**: https://designpattern.fyi/patterns/encapsulation/

---

## Description
**Intent**: External code that writes directly to internal fields can put an object in an invalid state. Encapsulation forces all modifications through methods that enforce invariants before applying changes.

**Context**: A BankAccount with a public balance field can be set to any value by any caller — including -∞. Encapsulation makes callers use deposit() and withdraw() — the only paths that enforce the rule "balance can't go negative."

**Solution**: Declare internal fields as private using access modifiers. Provide public methods (getters, setters, domain operations) that validate inputs before modifying state. The object's invariants are enforced at its boundary — not relied upon by every caller.



## Use Cases
Any object with business rules about valid state. When direct field access could leave the object broken or inconsistent. When implementation details should be free to change without callers noticing.



## Implementation Example

```javascript
class BankAccount {
  #balance; // Private field

  constructor(initialBalance) {
    this.#balance = initialBalance;
  }

  deposit(amount) {
    if (amount > 0) {
      this.#balance += amount;
    }
  }

  withdraw(amount) {
    if (amount > 0 && this.#balance >= amount) {
      this.#balance -= amount;
      return true;
    }
    return false;
  }

getBalance() {
    return this.#balance;
  }
}

const account = new BankAccount(100);
account.deposit(50);
console.log(account.getBalance()); // 150
```



## Trade-offs


### Advantages

- Invalid states become impossible — invariants are enforced at the boundary

- Internal implementation can change without breaking any caller

- Validation logic lives in one place, not scattered across every call site

- Easier to maintain and refactor — the surface area of change is the class itself




### Considerations & Drawbacks

- Adds boilerplate — getters, setters, and access modifiers for every field

- Fine-grained encapsulation can add overhead in performance-critical hot paths

- Over-encapsulation (wrapping every field with pass-through getters/setters and no logic) is ceremony without benefit







