UML & ModelingSequence DiagramsHard⏱️ ~4 min

Advanced: Combining Sequence Diagrams with Design Patterns

Using Sequence Diagrams to Validate Patterns

Sequence diagrams become powerful when combined with design patterns, showing not just what pattern you chose, but how it actually works in your system.

1. Strategy Pattern in Parking Fee Calculation

When interviewer asks "How do you handle different pricing strategies?", draw sequence diagram showing runtime strategy selection:

:ExitTerminal → :FeeCalculator: calculateFee(ticket, vehicle)
:FeeCalculator → :FeeCalculator: selectStrategy(vehicleType)
[returns :HourlyRateStrategy for COMPACT]
:FeeCalculator → :HourlyRateStrategy: calculate(duration)
:HourlyRateStrategy → :PricingConfig: getHourlyRate()
:PricingConfig ⤶ :HourlyRateStrategy: rate
[compute: duration * rate]
:HourlyRateStrategy ⤶ :FeeCalculator: amount
:FeeCalculator → :Money: «create»(amount)
:FeeCalculator ⤶ :ExitTerminal: fee:Money

Pattern validation: Sequence shows FeeCalculator delegates to strategy interface, not concrete classes. Easy to add FlatRateStrategy or DynamicPricingStrategy without changing FeeCalculator code (Open-Closed Principle).

2. Observer Pattern in Parking Spot Notifications

When spot becomes available, notify waiting customers:

:Vehicle → :ParkingLot: exit(ticket)
:ParkingLot → :ParkingSpot: markAvailable()
:ParkingLot → :SpotAvailabilitySubject: notifyObservers(spotType)
loop for each observer
:SpotAvailabilitySubject → :WaitlistService: update(spotType)
:WaitlistService → :NotificationService: sendSMS(customer)
:SpotAvailabilitySubject → :DisplayBoard: update(spotType)
:DisplayBoard → :DisplayBoard: incrementAvailableCount()
end loop

Pattern validation: ParkingLot doesn't know about specific observers. WaitlistService and DisplayBoard react independently. Adding MobileAppObserver requires zero changes to ParkingLot.

Interview Tip: When you mention a pattern, draw mini sequence diagram showing the key interaction. This proves you understand the pattern deeply, not just memorized the name.
3. Chain of Responsibility in Vending Machine

Handling payment through multiple processors:

:Customer → :VendingMachine: selectProduct(item, payment)
:VendingMachine → :CashHandler: processPayment(payment)
[if payment is not cash]
:CashHandler → :CardHandler: processPayment(payment)
[if payment is not card]
:CardHandler → :MobilePayHandler: processPayment(payment)
[mobile payment succeeds]
:MobilePayHandler ⤶ :CardHandler: success
:CardHandler ⤶ :CashHandler: success
:CashHandler ⤶ :VendingMachine: paymentConfirmed
:VendingMachine → :Dispenser: dispenseProduct(item)

Pattern validation: Each handler tries to process or passes to next handler. Chain is extensible (add CryptocurrencyHandler) without modifying existing handlers.

4. Factory Pattern in Vehicle Creation
:EntryTerminal → :VehicleFactory: createVehicle(licensePlate, type)
[if type == MOTORCYCLE]
:VehicleFactory → :Motorcycle: «create»(licensePlate)
:Motorcycle ⤶ :VehicleFactory: motorcycle
[else if type == CAR]
:VehicleFactory → :Car: «create»(licensePlate)
:Car ⤶ :VehicleFactory: car
:VehicleFactory ⤶ :EntryTerminal: vehicle:Vehicle
:EntryTerminal → :ParkingLot: findSpot(vehicle)

Pattern validation: EntryTerminal works with Vehicle interface, doesn't care about concrete type. Factory encapsulates instantiation logic. Adding Truck only modifies factory, not clients.

5. Decorator Pattern in Fee Calculation

Adding surcharges and discounts:

:ExitTerminal → :BaseFeeCalculator: calculateFee(ticket)
:BaseFeeCalculator ⤶ :ExitTerminal: baseFee = $10
:ExitTerminal → :WeekendSurchargeDecorator: calculateFee(ticket)
:WeekendSurchargeDecorator → :BaseFeeCalculator: calculateFee(ticket)
:BaseFeeCalculator ⤶ :WeekendSurchargeDecorator: $10
[apply 20% surcharge: $10 * 1.2 = $12]
:WeekendSurchargeDecorator ⤶ :ExitTerminal: $12
:ExitTerminal → :MemberDiscountDecorator: calculateFee(ticket)
:MemberDiscountDecorator → :WeekendSurchargeDecorator: calculateFee(ticket)
:WeekendSurchargeDecorator ⤶ :MemberDiscountDecorator: $12
[apply 10% discount: $12 * 0.9 = $10.80]
:MemberDiscountDecorator ⤶ :ExitTerminal: finalFee = $10.80

Pattern validation: Decorators wrap each other, each adding behavior. Order matters (surcharge before discount). Can mix-and-match decorators at runtime.

Interview Tip: If you claim "I'll use Strategy pattern for pricing," interviewer might ask "Show me the sequence." Be ready to sketch how objects interact at runtime, proving the pattern actually simplifies your design.
Common Interview Question: Pattern Comparison

"Why use Strategy over if-else for pricing?" Draw both sequences:

Without Pattern
calculateFee() {
  if (type == HOURLY)
    // logic
  else if (type == FLAT)
    // logic
}
Violates Open-Closed, hard to test individual strategies
With Strategy
calculator.calculate()
  → strategy.calculate()

Each strategy isolated
Each strategy testable independently, new strategies don't modify calculator

The sequence diagram makes it obvious why Strategy is superior: delegation to pluggable component versus monolithic conditional logic.

💡 Key Takeaways
Sequence diagrams validate that patterns actually work in your design
Strategy pattern shows delegation to interchangeable algorithm objects
Observer pattern shows one-to-many notification without tight coupling
Chain of Responsibility shows request passing through handler chain
Decorator pattern shows wrapping and behavior layering in sequence
📌 Examples
1Strategy: FeeCalculator delegates to HourlyRateStrategy vs FlatRateStrategy
2Observer: ParkingLot notifies WaitlistService and DisplayBoard on spot availability
3Chain: Payment handlers try processing sequentially until one succeeds
4Factory: VehicleFactory creates Motorcycle or Car based on type parameter
← Back to Sequence Diagrams Overview
Advanced: Combining Sequence Diagrams with Design Patterns | Sequence Diagrams - System Overflow