@startuml
'skinparam linetype ortho

interface IDoor {
	open()
	close()
	is_open()
	is_obstructed()
}
interface IObstruction_Sensor {
	is_obstructed()
}

class Controller {
	requests[]

	add_request(request)
	handle_requests()
}
class Elevator {
	current_floor
	requested_floor

	open()
	close()
	is_open()
	move()
	set_floor(floor)
	request_floor(floor)
}
class Floor {
	elevator

	request_elevator()
	handle_elevator()
	open()
	close()
	is_open()
}
note right
Floor passes a handle_elevator
as a callback function to Elevator_Sensor
This callback is called once an
elevator is detected.
end note
class Door {
	state

	open()
	close()
	is_open()
	is_obstructed()
}
class Pressure_Sensor {
	is_obstructed()
}
class Optical_Sensor {
	is_obstructed()
}
class Tension_Sensor {
	callback

	Tension_Sensor(callback)
}
class Catch_Clamp {
	initiate()
}
note top
Catch_Clamp will initialize
Tension_Sensor with initiate
as callback. This callback
is called once a change is
detected. This system runs
independently from the rest
but can be read from controller.
end note
class Floor_Indicator {
	update(value)
}
class Elevator_Sensor {
	callback

	Elevator_Sensor(callback)
}
class Button {
	is_pressed()
}
class Numpad {
	buttons[]

	get_value()
}
class Speaker {
	play_sound()
}

Controller			"1" o--- "*"	Floor
Controller			"1" o--- "*"	Elevator
IDoor					<|..		Door
Elevator			"1" o-- "1"		IDoor
Floor				"1" o-- "*"		IDoor
Floor				"1" o-- "*"		IObstruction_Sensor
IObstruction_Sensor		<|..		Pressure_Sensor
IObstruction_Sensor		<|..		Optical_Sensor
Elevator			"1" o-- "1"		Floor_Indicator
Floor				"1" o-- "*"		Floor_Indicator
Elevator			"1" o-- "1"		Numpad
Floor				"1" o- "*"		Button
Numpad				"1" o-- "*"		Button
Floor				"1" o-- "*"		Elevator_Sensor
Floor				"1" o-- "*"		Speaker

Catch_Clamp			"1" *-- "1"		Tension_Sensor

@enduml