Lift Sistem Dizaynı
Problem Təsviri
Binada çoxlu liftləri effektiv şəkildə idarə edə bilən, müxtəlif mərtəbələrdəki istifadəçilərin sorğularını işləyən və lift hərəkətini optimallaşdıran lift sistemi dizayn edin.
Tələblər
-
Funksional Tələblər:
- Binada çoxlu liftlər dəstəyi
- Xarici sorğuların (mərtəbələrdən) və daxili sorğuların (lift içindən) işlənməsi
- Liftlərin yuxarı və aşağı hərəkəti
- Qapıların açılması və bağlanması
- Cari mərtəbə və istiqamətin göstərilməsi
- Təcili dayanma dəstəyi
-
Qeyri-Funksional Tələblər:
- Təhlükəsizlik (qapıların maneə olduqda bağlanmasının qarşısının alınması)
- Effektivlik (gözləmə müddətinin və enerji sərfiyyatının minimuma endirilməsi)
- Etibarlılıq
- Concurrent sorğular üçün thread safety
Əsas Komponentlər
- Lift Kabinası: Mərtəbələr arasında hərəkət edən fiziki lift
- Lift Kontrolleri: Liftin hərəkətini və əməliyyatlarını idarə edir
- Planlaşdırıcı: Sorğuları optimallaşdırma alqoritminə əsasən liftlərə təyin edir
- Düymə Paneli: Hər lift daxilində və hər mərtəbədə
- Ekran: Cari mərtəbə və istiqaməti göstərir
Dizayn Yanaşması
Lift vəziyyətlərini modelləşdirmək üçün State Pattern istifadə edəcəyik:
- Idle: Lift sakit vəziyyətdə, qapılar bağlı
- Moving Up: Lift yuxarı hərəkət edir
- Moving Down: Lift aşağı hərəkət edir
- Doors Opening: Lift qapıları açılır
- Doors Open: Lift qapıları tam açıq
- Doors Closing: Lift qapıları bağlanır
İcra
Koda bax
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
// Elevator state interface
interface ElevatorState {
void handleRequest(Elevator elevator, int floor);
void move(Elevator elevator);
void stop(Elevator elevator);
void openDoors(Elevator elevator);
void closeDoors(Elevator elevator);
}
// Idle state
class IdleState implements ElevatorState {
@Override
public void handleRequest(Elevator elevator, int floor) {
if (floor > elevator.getCurrentFloor()) {
elevator.setDirection(Direction.UP);
elevator.setState(new MovingUpState());
} else if (floor < elevator.getCurrentFloor()) {
elevator.setDirection(Direction.DOWN);
elevator.setState(new MovingDownState());
} else {
elevator.openDoors();
}
}
@Override
public void move(Elevator elevator) {
// Cannot move in idle state
}
@Override
public void stop(Elevator elevator) {
// Already stopped
}
@Override
public void openDoors(Elevator elevator) {
elevator.setState(new DoorsOpeningState());
}
@Override
public void closeDoors(Elevator elevator) {
// Doors already closed
}
}
// Moving Up state
class MovingUpState implements ElevatorState {
@Override
public void handleRequest(Elevator elevator, int floor) {
if (floor >= elevator.getCurrentFloor()) {
elevator.addRequest(floor);
}
}
@Override
public void move(Elevator elevator) {
elevator.moveUp();
if (elevator.shouldStopAtCurrentFloor()) {
elevator.stop();
}
}
@Override
public void stop(Elevator elevator) {
elevator.setState(new IdleState());
elevator.openDoors();
}
@Override
public void openDoors(Elevator elevator) {
// Cannot open doors while moving
}
@Override
public void closeDoors(Elevator elevator) {
// Doors already closed
}
}
// Moving Down state
class MovingDownState implements ElevatorState {
@Override
public void handleRequest(Elevator elevator, int floor) {
if (floor <= elevator.getCurrentFloor()) {
elevator.addRequest(floor);
}
}
@Override
public void move(Elevator elevator) {
elevator.moveDown();
if (elevator.shouldStopAtCurrentFloor()) {
elevator.stop();
}
}
@Override
public void stop(Elevator elevator) {
elevator.setState(new IdleState());
elevator.openDoors();
}
@Override
public void openDoors(Elevator elevator) {
// Cannot open doors while moving
}
@Override
public void closeDoors(Elevator elevator) {
// Doors already closed
}
}
// Doors Opening state
class DoorsOpeningState implements ElevatorState {
@Override
public void handleRequest(Elevator elevator, int floor) {
elevator.addRequest(floor);
}
@Override
public void move(Elevator elevator) {
// Cannot move while doors are opening
}
@Override
public void stop(Elevator elevator) {
// Already stopped
}
@Override
public void openDoors(Elevator elevator) {
// Doors are already opening
}
@Override
public void closeDoors(Elevator elevator) {
// Cannot close doors while they are opening
}
// Transition to doors open state after doors finish opening
public void doorsOpened(Elevator elevator) {
elevator.setState(new DoorsOpenState());
}
}
// Doors Open state
class DoorsOpenState implements ElevatorState {
@Override
public void handleRequest(Elevator elevator, int floor) {
elevator.addRequest(floor);
}
@Override
public void move(Elevator elevator) {
// Cannot move while doors are open
}
@Override
public void stop(Elevator elevator) {
// Already stopped
}
@Override
public void openDoors(Elevator elevator) {
// Doors already open
}
@Override
public void closeDoors(Elevator elevator) {
elevator.setState(new DoorsClosingState());
}
}
// Doors Closing state
class DoorsClosingState implements ElevatorState {
@Override
public void handleRequest(Elevator elevator, int floor) {
if (floor == elevator.getCurrentFloor()) {
// Reopen doors if request is for current floor
elevator.openDoors();
} else {
elevator.addRequest(floor);
}
}
@Override
public void move(Elevator elevator) {
// Cannot move while doors are closing
}
@Override
public void stop(Elevator elevator) {
// Already stopped
}
@Override
public void openDoors(Elevator elevator) {
elevator.setState(new DoorsOpeningState());
}
@Override
public void closeDoors(Elevator elevator) {
// Doors already closing
}
// Transition to idle state after doors finish closing
public void doorsClosed(Elevator elevator) {
elevator.setState(new IdleState());
elevator.processNextRequest();
}
}
// Direction enum
enum Direction {
UP, DOWN, NONE
}
// Elevator class
class Elevator {
private final int id;
private int currentFloor;
private Direction direction;
private ElevatorState state;
private final Set<Integer> upRequests;
private final Set<Integer> downRequests;
private final int maxFloor;
private final Lock lock;
private boolean doorObstructed;
public Elevator(int id, int maxFloor) {
this.id = id;
this.currentFloor = 1;
this.direction = Direction.NONE;
this.state = new IdleState();
this.upRequests = new ConcurrentSkipListSet<>();
this.downRequests = new ConcurrentSkipListSet<>(Collections.reverseOrder());
this.maxFloor = maxFloor;
this.lock = new ReentrantLock();
this.doorObstructed = false;
}
public int getId() {
return id;
}
public int getCurrentFloor() {
return currentFloor;
}
public Direction getDirection() {
return direction;
}
public void setDirection(Direction direction) {
this.direction = direction;
}
public void setState(ElevatorState state) {
this.state = state;
}
public void addRequest(int floor) {
if (floor < 1 || floor > maxFloor) {
throw new IllegalArgumentException("Invalid floor: " + floor);
}
if (floor > currentFloor) {
upRequests.add(floor);
} else if (floor < currentFloor) {
downRequests.add(floor);
}
}
public void handleRequest(int floor) {
lock.lock();
try {
state.handleRequest(this, floor);
} finally {
lock.unlock();
}
}
public void moveUp() {
if (currentFloor < maxFloor) {
currentFloor++;
System.out.println("Elevator " + id + " moved up to floor " + currentFloor);
}
}
public void moveDown() {
if (currentFloor > 1) {
currentFloor--;
System.out.println("Elevator " + id + " moved down to floor " + currentFloor);
}
}
public void move() {
lock.lock();
try {
state.move(this);
} finally {
lock.unlock();
}
}
public void stop() {
lock.lock();
try {
state.stop(this);
System.out.println("Elevator " + id + " stopped at floor " + currentFloor);
} finally {
lock.unlock();
}
}
public void openDoors() {
lock.lock();
try {
state.openDoors(this);
System.out.println("Elevator " + id + " doors opening at floor " + currentFloor);
// Simulate doors opening
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
if (state instanceof DoorsOpeningState) {
((DoorsOpeningState) state).doorsOpened(this);
System.out.println("Elevator " + id + " doors open at floor " + currentFloor);
}
} finally {
lock.unlock();
}
}
public void closeDoors() {
lock.lock();
try {
if (doorObstructed) {
System.out.println("Elevator " + id + " doors obstructed, reopening");
doorObstructed = false;
openDoors();
return;
}
state.closeDoors(this);
System.out.println("Elevator " + id + " doors closing at floor " + currentFloor);
// Simulate doors closing
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
if (state instanceof DoorsClosingState) {
((DoorsClosingState) state).doorsClosed(this);
System.out.println("Elevator " + id + " doors closed at floor " + currentFloor);
}
} finally {
lock.unlock();
}
}
public boolean shouldStopAtCurrentFloor() {
if (direction == Direction.UP && upRequests.contains(currentFloor)) {
upRequests.remove(currentFloor);
return true;
} else if (direction == Direction.DOWN && downRequests.contains(currentFloor)) {
downRequests.remove(currentFloor);
return true;
}
return false;
}
public void processNextRequest() {
if (!upRequests.isEmpty() && (direction == Direction.UP || downRequests.isEmpty())) {
direction = Direction.UP;
int nextFloor = upRequests.iterator().next();
handleRequest(nextFloor);
} else if (!downRequests.isEmpty()) {
direction = Direction.DOWN;
int nextFloor = downRequests.iterator().next();
handleRequest(nextFloor);
} else {
direction = Direction.NONE;
}
}
public void simulateDoorObstruction() {
doorObstructed = true;
}
public void emergencyStop() {
lock.lock();
try {
System.out.println("Elevator " + id + " EMERGENCY STOP at floor " + currentFloor);
state = new IdleState();
direction = Direction.NONE;
upRequests.clear();
downRequests.clear();
} finally {
lock.unlock();
}
}
}
// Elevator Controller class
class ElevatorController {
private final List<Elevator> elevators;
private final int maxFloor;
public ElevatorController(int elevatorCount, int maxFloor) {
this.elevators = new ArrayList<>();
this.maxFloor = maxFloor;
for (int i = 1; i <= elevatorCount; i++) {
elevators.add(new Elevator(i, maxFloor));
}
}
public void requestElevator(int floor, Direction direction) {
if (floor < 1 || floor > maxFloor) {
throw new IllegalArgumentException("Invalid floor: " + floor);
}
// Find the best elevator to handle this request
Elevator bestElevator = findBestElevator(floor, direction);
bestElevator.handleRequest(floor);
}
public void requestFloor(int elevatorId, int floor) {
if (elevatorId < 1 || elevatorId > elevators.size()) {
throw new IllegalArgumentException("Invalid elevator ID: " + elevatorId);
}
if (floor < 1 || floor > maxFloor) {
throw new IllegalArgumentException("Invalid floor: " + floor);
}
Elevator elevator = elevators.get(elevatorId - 1);
elevator.handleRequest(floor);
}
private Elevator findBestElevator(int floor, Direction direction) {
// Simple algorithm: find the closest idle elevator or one moving in the same direction
Elevator bestElevator = null;
int minDistance = Integer.MAX_VALUE;
for (Elevator elevator : elevators) {
if (elevator.getDirection() == Direction.NONE) {
// Idle elevator
int distance = Math.abs(elevator.getCurrentFloor() - floor);
if (distance < minDistance) {
minDistance = distance;
bestElevator = elevator;
}
} else if (elevator.getDirection() == direction) {
// Elevator moving in the same direction
if ((direction == Direction.UP && elevator.getCurrentFloor() < floor) ||
(direction == Direction.DOWN && elevator.getCurrentFloor() > floor)) {
int distance = Math.abs(elevator.getCurrentFloor() - floor);
if (distance < minDistance) {
minDistance = distance;
bestElevator = elevator;
}
}
}
}
// If no suitable elevator found, just pick the first one
if (bestElevator == null) {
bestElevator = elevators.get(0);
}
return bestElevator;
}
public void step() {
// Simulate one time step for all elevators
for (Elevator elevator : elevators) {
if (elevator.getDirection() != Direction.NONE) {
elevator.move();
}
}
}
}
// Example usage
public class ElevatorSystemDemo {
public static void main(String[] args) {
// Create a controller with 3 elevators and 10 floors
ElevatorController controller = new ElevatorController(3, 10);
// Request elevators from different floors
controller.requestElevator(5, Direction.UP);
controller.requestElevator(3, Direction.DOWN);
// Simulate time steps
for (int i = 0; i < 10; i++) {
controller.step();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
// Request a specific floor from inside an elevator
controller.requestFloor(1, 8);
// Simulate more time steps
for (int i = 0; i < 10; i++) {
controller.step();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
Thread Safety Considerations
- ReentrantLock: Liftlərdə thread-safe əməliyyatları təmin etmək üçün istifadə olunur
- ConcurrentSkipListSet: Mərtəbə sorğularının thread-safe idarə edilməsi üçün istifadə olunur
- State Pattern: Lift vəziyyət keçidlərinin atomik və tutarlı olmasını təmin edir
- Immutable Objects: Direction enum və state implementasiyaları dəyişməzdir
Optimallaşdırma Strategiyaları
- Ən Yaxın Lift Alqoritmi: Sorğuları ən yaxın mövcud liftə təyin edir
- Eyni İstiqamət Prioriteti: Artıq tələb olunan istiqamətdə hərəkət edən liftlərə prioritet verir
- Skan Alqoritmi (Lift Alqoritmi): Bir istiqamətdə həmin istiqamətdə daha çox sorğu qalmayana qədər xidmət edir
- İrəliyə Baxış Strategiyası: Nümunələr əsasında gələcək sorğuları proqnozlaşdırır
Təhlükəsizlik Xüsusiyyətləri
- Qapı Maneə Aşkarlaması: Maneə olduqda qapıların bağlanmasının qarşısını alır
- Təcili Dayanma: Lifti dərhal dayandırır və bütün sorğuları təmizləyir
- Mərtəbə Doğrulaması: Sorğu olunan mərtəbələrin etibarlı diapazonda olmasını təmin edir
- Vəziyyət Doğrulaması: Cari vəziyyətə əsasən yanlış əməliyyatların qarşısını alır
Əlavə Xüsusiyyətlər
- Çəki Məhdudiyyəti Aşkarlaması: Liftin həddindən artıq yüklənməsinin qarşısını alır
- Prioritet Xidməti: Prioritet sorğularını dəstəkləyir (məsələn, təcili yardım personalı üçün)
- Ekspress Liftlər: Yalnız müəyyən mərtəbələrdə dayanan liftlər
- Texniki Xidmət Rejimi: Texniki xidmət üçün liftləri xidmətdən çıxarır