Loading page…
One diagram with all six relationships at once (inheritance, realisation, composition, aggregation, association, dependency), written as code the tests can tell apart.
A small hotel takes bookings. This is the diagram an interviewer would ask you to draw, and it uses every relationship the lesson teaches. Before you code, read each line aloud: what is it, and what does it look like in code?
%% title: The hotel
classDiagram
class Hotel {
+name str
+rooms list
+guests list
+bookings list
+register(guest)
+book(room_number, guest, nights) Booking
+check_out(booking)
}
class Room {
+number int
+rate int
+nightly_rate(policy) int
}
class Suite {
+nightly_rate(policy) int
}
class Guest {
+name str
}
class Booking {
+nights int
+cost(policy) int
}
class PricingPolicy {
<<interface>>
+apply(rate) int
}
class FlatPricing
class WeekendPricing {
+percent int
}
Hotel "1" *-- "1..*" Room : rooms
Hotel "1" *-- "*" Booking : bookings
Hotel "*" o-- "*" Guest : guests
Room <|-- Suite
Booking "*" --> "1" Room : of
Booking "*" --> "1" Guest : for
Booking ..> PricingPolicy : priced by
Room ..> PricingPolicy : priced by
PricingPolicy <|.. FlatPricing
PricingPolicy <|.. WeekendPricingBuild this API (names are Python's; JavaScript and TypeScript use camelCase where they differ: nightlyRate, checkOut, roomNumber):
PricingPolicy is the interface: apply(rate) is abstract. Building it, or an implementation without apply, raises TypeError (JavaScript: Error containing interface). FlatPricing() returns the rate unchanged. WeekendPricing(percent) returns rate * (100 + percent) // 100 (whole rupees).Room(number, rate) with .number, .rate. nightly_rate(policy) is policy.apply(self.rate). Suite(number, rate) is a Room and adds 1000 to the policy's price for the room: policy.apply(rate) + 1000.Guest(name) with .name.Booking(room, guest, nights) refers to the very room and guest it is given. nights is 1 to 30: otherwise ValueError (Error containing nights). cost(policy) is nights * room.nightly_rate(policy); the policy is only a parameter.Hotel(name, room_specs): room_specs is a list of (number, rate, is_suite). The hotel creates a Room for each (a Suite when is_suite is true) in .rooms. A hotel needs at least one room (1..*): an empty list raises ValueError (Error containing at least one room). .guests and .bookings start empty.Hotel.register(guest) keeps the very guest it is given, never a copy (aggregation).Hotel.book(room_number, guest, nights) creates a Booking for the room with that number, keeps it in .bookings and returns it. It raises ValueError for an unknown room (Error containing no room), for a guest who is not registered (Error containing not registered), and for a room that already has a booking (Error containing occupied). A refused call changes nothing.Hotel.check_out(booking) removes the booking, freeing the room. A booking that is not in .bookings raises ValueError (Error containing not an active booking).Write your code, then run 10 example tests and 3 hidden tests. Each run is limited to 8 seconds: an infinite loop gets stopped and the runtime restarts, your code stays.