Determine the different ways the system will be used. This includes main functions the system needs to perform and who will use it.
id, currentFloor, direction, and status.moveToFloor(), openDoors(), and closeDoors().floor, requestType (up or down), and possibly a timestamp.id, name, and possible location requests.1 to many relationship).1 to many relationship).1 to many relationship).1 to many relationship).1 to many relationship).Elevator
+int id
+int currentFloor
+String direction
+String status
+moveToFloor(int floor)
Request
+int floor
+String requestType
+User user
Building
+List elevators
+List requests
+Controller controller
User
+int id
+String name
+List requests
Controller
+List elevators
+List requests
+processRequest(Request request)
+optimizeMovements()
The Singleton Pattern ensures that a class has only one instance and provides a global point of access to it. This is useful for the Controller class because we want a single controller managing all elevator requests and their movements.
Controller should manage the elevator state and user requests, meaning we wouldn't want multiple instances accidentally modifying the same state.The Strategy Pattern allows us to define a family of algorithms, encapsulate each one, and make them interchangeable. This pattern is helpful for elevator movement strategies, whereby different algorithms can be applied based on the system load or type of requests.
Controller dynamically based on the state of the system.The Observer Pattern provides a way for one object (the subject) to notify observers when its state changes. This can be applied if we want to implement real-time updates for users when an elevator arrives or when status changes.
The Factory Pattern helps create objects without specifying the exact class of object that will be created. This can be helpful when creating different types of requests or elevators based on the conditions (like EmergencyRequest or FreightElevator).
RequestFactory can instantiate different types of requests based on input, while an ElevatorFactory can create either standard or freight elevators.The Command Pattern encapsulates a request as an object, thereby allowing for parameterization of clients with queues, requests, and operations. This can control actions like moving elevators, opening doors, and processing requests.
MoveElevatorCommand, OpenDoorCommand) can be executed by the controller, encapsulating the specifics of how these actions are performed.Attributes: For each class, define the attributes (data) it will hold...
Methods: Define the methods (functions) that operate on the attributes. Ensure they align with the object's responsibilities and adhere to the principle of encapsulation.
import java.util.ArrayList;
import java.util.List;
public class Building {
private List<Elevator> elevators;
private RequestManager requestManager;
public Building(RequestManager requestManager) {
elevators = new ArrayList<>();
this.requestManager = requestManager;
}
public void addElevator(Elevator elevator) {
elevators.add(elevator);
requestManager.registerElevator(elevator); // Register newly added elevators
}
public void requestElevator(Request request) {
requestManager.processRequest(request);
}
}
public abstract class Elevator {
protected int id;
protected int currentFloor;
protected String direction;
protected String status;
public Elevator(int id) {
this.id = id;
this.currentFloor = 0;
this.direction = "Idle";
this.status = "Idle";
}
public void moveToFloor(int floor) {
// Logic to move the elevator to the requested floor
}
public void openDoors() {
status = "Doors Open";
}
public void closeDoors() {
status = "Doors Closed";
}
// Getters and Setters
}
public class StandardElevator extends Elevator {
private int passengerCapacity;
public StandardElevator(int id, int passengerCapacity) {
super(id);
this.passengerCapacity = passengerCapacity;
}
// Additional methods specific to StandardElevator
}
public class FreightElevator extends Elevator {
private int loadCapacity;
public FreightElevator(int id, int loadCapacity) {
super(id);
this.loadCapacity = loadCapacity;
}
// Additional methods specific to FreightElevator
}
public abstract class Request {
protected int floor;
protected String requestType;
protected User user;
public Request(int floor, String requestType, User user) {
this.floor = floor;
this.requestType = requestType;
this.user = user;
}
// Getters and Setters
}
public class RegularRequest extends Request {
public RegularRequest(int floor, User user) {
super(floor, "Regular", user);
}
}
public class EmergencyRequest extends Request {
public EmergencyRequest(int floor, User user) {
super(floor, "Emergency", user);
}
}
import java.util.List;
public class RequestManager {
private Controller controller;
public RequestManager(Controller controller) {
this.controller = controller;
}
public void registerElevator(Elevator elevator) {
controller.registerElevator(elevator);
}
public void processRequest(Request request) {
controller.processRequest(request);
}
}
public interface Controller {
void processRequest(Request request);
void registerElevator(Elevator elevator);
void optimizeMovements();
}
public class SimpleController implements Controller {
private List<Elevator> elevators = new ArrayList<>();
@Override
public void processRequest(Request request) {
// Simple processing logic, selecting the nearest elevator
optimizeMovements();
}
@Override
public void registerElevator(Elevator elevator) {
elevators.add(elevator);
}
@Override
public void optimizeMovements() {
// Execution of optimization logic for elevating sequence
}
}
public class AdvancedController implements Controller {
private List<Elevator> elevators = new ArrayList<>();
@Override
public void processRequest(Request request) {
// Utilize a more complex routing algorithm
optimizeMovements();
}
@Override
public void registerElevator(Elevator elevator) {
elevators.add(elevator);
}
@Override
public void optimizeMovements() {
// Advanced optimization logic
}
}
public class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
public void makeRequest(Building building, int floor) {
Request request = new RegularRequest(floor, this);
building.requestElevator(request);
}
// Getters and Setters
Check and explain whether your design adheres to solid principles (Ask interviewer what SOLID principle is if you can not recall it.)...
Explain how your design can handle changes in scale and whether it would be easily to extend with new functionalities...
Try creating a class, flow, state and/or sequence diagram using the diagramming tool. Mermaid flow diagrams can be used to represent system use cases. You can ask the interviewer bot to create a starter diagram if unfamiliar with the tool. Briefly explain your diagrams if necessary...
Critically examine your design for any flaws or areas for future improvement...