1. ATM State Machine Flow
An ATM cycles through strict states: IDLE -> CARD_INSERTED -> PIN_AUTHENTICATED -> TRANSACTION_SELECTED -> CASH_DISPENSING -> CARD_EJECTED. Disallowing operations out of sequence (e.g. withdrawing cash before PIN verification) is guaranteed by the State Pattern.
2. Cash Dispenser: Chain of Responsibility Pattern
An ATM holds currency notes of various denominations ($100, $50, $20, $10). To dispense an arbitrary withdrawal amount (e.g. $370), we employ the Chain of Responsibility pattern.
Each handler dispenses the maximum number of its denomination, then delegates the remaining balance to the next handler down the chain. If exact change cannot be formed, the transaction is rejected atomically.
3. Complete Code Snippet
Here is the cash dispenser chain implementation:
abstract class CashDispenser {
protected nextDispenser?: CashDispenser;
constructor(protected denomination: number) {}
public setNext(next: CashDispenser) { this.nextDispenser = next; }
public dispense(amount: number): void {
const count = Math.floor(amount / this.denomination);
const remainder = amount % this.denomination;
if (count > 0) console.log(`Dispensing ${count} notes of $${this.denomination}`);
if (remainder > 0 && this.nextDispenser) {
this.nextDispenser.dispense(remainder);
}
}
}
class HundredDispenser extends CashDispenser { constructor() { super(100); } }
class FiftyDispenser extends CashDispenser { constructor() { super(50); } }
class TwentyDispenser extends CashDispenser { constructor() { super(20); } }Model this architecture on the HLDForge Canvas
Turn static box diagrams into living, collaborative systems. Drag and drop microservices, Kafka clusters, and cache tiers. Run automated SPOF detection and STRIDE threat modeling in real time.
Written by HLDForge Architecture Team
Lead Machine Coding Specialist
The HLDForge Architecture Team publishes practical engineering guides, real-world case studies, and high-concurrency blueprints to help engineers build scalable and fault-tolerant software.