Movie Ticket Booking System in Java: Seat Holds and Pricing
Code a BookMyShow-style booking system in Java: ShowSeat state, all-or-none holds that expire, payment that confirms or releases, and pricing as a Strategy.
- Course: Low-Level Design study plan
- Module: Movie ticket booking
- Kind: Lesson
- Reading time: 14 min
- Runtime: OpenJDK 18
How do you code a movie ticket booking system in a machine-coding round?
Keep one ShowSeat per seat per show with a status (available, held or booked), the holder and a hold expiry. A hold takes all the chosen seats or none, for a fixed time; a successful payment marks them booked, a failed one releases them at once, and a lapsed hold simply reads as available. Pricing sits behind a Strategy.
Lesson
A booking system sells a contested resource: one seat, one show, one buyer. The machine-coding version tests three things: the seat state, the hold that expires, and keeping rules such as pricing out of the core. The movie ticket booking note has the whole design, including the database locks; here you build the in-memory model.
The classes
- Seat: physical, never changes (
A1, row and number). - ShowSeat: one seat for one show:
status(AVAILABLE, HELD, BOOKED),holder,heldUntil. All the action is here, not on Seat. - Show: the seat map, in layout order, with
hold,payandshow. - PricingStrategy:
price(seat), swapped per show: weekday, weekend, matinee.
The flow, as commands
HOLD user seats…: check every seat first; if all are free, hold them all untilnow + hold.PAY user ok: the user's still-held seats become BOOKED.PAY user fail: they are released at once, not when the hold runs out.TICK n: time passes. A hold whose time is up is read as available; nothing has to fire.
1 4 5 · HOLD alice A1 A2 · HOLD bob A2 A3 · TICK 2 · PAY alice fail …- Four seats for one show, all available; a hold lasts 5 minutes. The clock is the script's own: it moves only on TICK.
- alice holds A1 and A2 together. Both are free, so both become HELD by her until t=5.
- bob wants A2 and A3. A2 is alice's, so the hold is refused whole: bob gets nothing, not even the free A3.
- Two minutes pass. Nothing is fired; the holds just have less time left.
- alice's card is declined. Her seats are released at once, not at t=5, so nobody is kept waiting for a payment that has already failed.
- bob tries again and gets A2 and A3 together, until t=7.
- Another minute: it is t=3, and bob's hold is still good.
- bob's payment succeeds while his hold is valid, so A2 and A3 become BOOKED for this show.
- carol holds A1 until t=8. She never pays.
- The clock reaches t=8. carol's hold is still stored on the seat, but it is read as lapsed: A1 shows as available without any timer.
- dave asks for A1 and gets it: a lapsed hold is free to take, until t=13.
The traps
- Half a hold. Holding seats one at a time and failing on the third leaves two held. Check all, then change all.
- A timer per hold. Threads and schedulers make the output depend on timing. Store
heldUntiland compare it with the clock whenever the seat is read. - Paying for a lapsed hold. A payment confirms only what is still held by that user; if the hold lapsed, the seat may already be someone else's.
- Status on Seat. A seat is booked for one show, not for ever. Status lives on ShowSeat.
Pricing as a Strategy
The second exercise adds seat categories by row and a pricing rule chosen per show. The rule is one interface with one method; the booking code asks it for a price and never names a day of the week. A new rule, a festival surcharge say, is one more class. Prices are whole rupees here, so no floating point ever touches the money.
Common questions
Why does a booking system hold seats before taking payment?
So nobody pays for a seat that is already gone. The hold reserves the seats for a few minutes while the payment runs; success books them, failure releases them, and an abandoned checkout lapses on its own when the hold expires.
How do you expire a seat hold without a background job?
Store the expiry time on the seat and treat a HELD seat whose expiry has passed as available whenever it is read. No timer has to fire; a cleanup job can still tidy the rows later, but correctness never depends on it.
Why must a multi-seat hold be all or none?
A buyer who asked for two seats together does not want one of them. Check every seat first and change none if any is taken; changing seats one by one would leave a half-held booking when a later seat fails.
What should happen if a payment succeeds after the hold has lapsed?
Confirm only seats that are still held by this buyer; if the hold lapsed, the seats may already belong to someone else, so the booking fails and the money is refunded. The exercise prints that as "has no active hold".
Exercises
Holds that expire
Model one show's seats with holds and payments.
Input. The first line is rows cols hold: rows are lettered A, B, … and seats numbered 1 to cols (A1, A2, …), and a hold lasts hold minutes. The clock starts at t=0. Then one command per line:
HOLD user s1 s2 …: all or none. Check the seats in the order given and stop at the first problem:user cannot hold S: no such seat,: bookedor: held(held by anyone, the same user included, and not lapsed). If every seat is free, hold them all untilnow + holdand printuser holds s1 s2 … until t=T(seats in the order given).PAY user okorPAY user fail: applies to every seat the user still holds (a hold is valid whilenow < heldUntil), taken in layout order.okbooks them:user booked A1 B2.failreleases them at once:user payment failed, released A1 B2. With no such seats:user has no active hold.TICK n: the clock moves onnminutes. Prints nothing.SHOW:t=N, then one line per row such asA: . H X ., where.is available (a lapsed hold included),Hheld andXbooked.
Seats in one command are distinct.
Example
1 3 5
HOLD alice A1 A2
HOLD bob A2 A3
PAY alice ok
SHOW
prints
alice holds A1 A2 until t=5
bob cannot hold A2: held
alice booked A1 A2
t=0
A: X X .Pricing as a Strategy
Price seats by category with a pricing rule chosen per show.
Input. The first line is rows cols (seats A1 … as before). The second line gives each row's category in order: REGULAR, PREMIUM or RECLINER, whose base prices are 200, 360 and 520 rupees. The show starts on the WEEKDAY rule. Then one command per line:
PRICING NAME: switch the rule and printpricing NAME, orunknown pricing NAME(the rule stays). The rules:WEEKDAYis the base price,WEEKENDis base × 5 / 4,MATINEEis base × 3 / 4, in whole rupees.QUOTE s1 s2 …:A1 250 + C2 450 = 700at the current rule (a single seat:A1 250 = 250), orno such seat Sfor the first unknown seat.BOOK user s1 s2 …: all or none, checked in order:user cannot book S: no such seator: booked. Otherwiseuser booked s1 s2 … for TOTALat the current rule.REVENUE:revenue N, the sum of every booking at the price it was sold for.
Example
3 4
REGULAR REGULAR PREMIUM
QUOTE A1 C2
PRICING WEEKEND
QUOTE A1 C2
prints
A1 200 + C2 360 = 560
pricing WEEKEND
A1 250 + C2 450 = 700In this module: Movie ticket booking
← Checkpoint: Elevator system · Checkpoint: Movie ticket booking →