"""
Door.py - Elevator door with state management and Observer pattern
Implements SOLID: Single Responsibility (door management only)
Open/Closed (extensible for new door types)
"""
from typing import List
from Direction import DoorState
class Observer:
"""
Observer interface for door state changes.
SOLID: Interface Segregation - minimal observer interface
"""
def update(self, door: 'Door') -> None:
"""Called when door state changes."""
pass
class Door:
"""
Represents an elevator door with state management.
Design Pattern: Observer (notifies subscribers of state changes)
SOLID Principles:
- Single Responsibility: Only manages door state
- Open/Closed: Can extend with new behaviors via observers
- Dependency Inversion: Depends on Observer interface, not concrete classes
"""
OPEN_TIME_SECONDS = 3 # Time door stays open
OPEN_CLOSE_TIME_SECONDS = 2 # Time to open or close
def __init__(self):
"""Initialize door in closed state."""
self._state = DoorState.CLOSED
self._observers: List[Observer] = []
self._open_timer = 0
def get_state(self) -> DoorState:
"""Get current door state."""
return self._state
def open(self) -> bool:
"""
Open the door.
Returns:
True if door opened successfully, False if already open/opening
"""
if self._state in (DoorState.OPEN, DoorState.OPENING):
return False
self._state = DoorState.OPENING
self._notify_observers()
# Simulate opening
self._state = DoorState.OPEN
self._notify_observers()
return True
def close(self) -> bool:
"""
Close the door.
Returns:
True if door closed successfully, False if already closed/closing
"""
if self._state in (DoorState.CLOSED, DoorState.CLOSING):
return False
self._state = DoorState.CLOSING
self._notify_observers()
# Simulate closing
self._state = DoorState.CLOSED
self._notify_observers()
return True
def is_open(self) -> bool:
"""Check if door is open."""
return self._state == DoorState.OPEN
def is_closed(self) -> bool:
"""Check if door is closed."""
return self._state == DoorState.CLOSED
def can_enter_exit(self) -> bool:
"""Check if passengers can safely enter/exit."""
return self._state == DoorState.OPEN
def subscribe(self, observer: Observer) -> None:
"""
Subscribe observer to door state changes.
SOLID: Dependency Injection - observer provided externally
"""
if observer not in self._observers:
self._observers.append(observer)
def unsubscribe(self, observer: Observer) -> None:
"""Unsubscribe observer from door state changes."""
if observer in self._observers:
self._observers.remove(observer)
def _notify_observers(self) -> None:
"""Notify all observers of state change."""
for observer in self._observers:
observer.update(self)
def __str__(self) -> str:
return f"Door(state={self._state})"
class ObservedDoor(Door):
"""
Extended Door with automatic logging of state changes.
Demonstrates SOLID Open/Closed principle - extends Door without modification.
"""
def __init__(self, door_id: int = 0):
super().__init__()
self.door_id = door_id
self.state_changes = []
def open(self) -> bool:
"""Open with logging."""
result = super().open()
if result:
self.state_changes.append(f"Door {self.door_id} opened to {self._state}")
return result
def close(self) -> bool:
"""Close with logging."""
result = super().close()
if result:
self.state_changes.append(f"Door {self.door_id} closed to {self._state}")
return result
def get_state_history(self) -> List[str]:
"""Get history of state changes."""
return self.state_changes.copy()