Servicio de alquiler de vehículos
Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy. Lección 87 de 87.
Para este desafío final, construirás un sistema de Servicio de Alquiler de Vehículos que reúne todos los conceptos de POO que has dominado a lo largo de este curso.
Su sistema debe modelar una flota de diferentes tipos de vehículos. Considere una clase base Vehicle con propiedades comunes como la matrícula, la marca y la tarifa de alquiler diaria. Las subclases como Car, Motorcycle y Truck pueden extender esto con atributos específicos como el número de asientos, el tamaño del motor o la capacidad de carga.
Las interfaces pueden definir comportamientos de alquiler: una interfaz Rentable podría declarar métodos como rent(), returnVehicle() y calculateCost(int days). Diferentes tipos de vehículos podrían implementar estrategias de precios de manera diferente, lo que hace que este sea un caso de uso perfecto para el polimorfismo.
Piensa en cómo la clase RentalAgency gestiona la flota utilizando composición.
Las excepciones personalizadas como VehicleNotAvailableException pueden manejar casos extremos.
Podrías aplicar el patrón Factory para crear vehículos o usar enums para las categorías de vehículos y el estado de alquiler.
Este desafío pone a prueba tu capacidad para diseñar un sistema OOP completo y bien estructurado. ¡Buena suerte!
Desafío
Fácil¡Construyamos un Servicio completo de alquiler de vehículos que reúna todo lo que has aprendido sobre POO! Crearás un sistema que administra una flota de diferentes tipos de vehículos, gestiona alquileres con la validación adecuada y utiliza un patrón de fábrica para crear vehículos.
Organizarás tu código en siete archivos:
RentalStatus.java: Crea un enum que represente el estado de alquiler de un vehículo. Incluye los valoresAVAILABLE,RENTEDyMAINTENANCE. Añade un campo privadodescription(String), un constructor y un getter. Available debe tener la descripción "ready to rent", rented debe tener "currently in use" y maintenance debe tener "under service".VehicleNotAvailableException.java: Crea una excepción personalizada que extiendaException. El constructor debe aceptar una matrícula y crear un mensaje con el formatoVehicle not available: [licensePlate].Rentable.java: Crea una interfaz que defina las operaciones de alquiler. Declara los métodosrent(), que devuelva un booleano,returnVehicle(), que devuelva un booleano, ycalculateCost(int days), que devuelva un double.Vehicle.java: Crea una clase base abstracta para todos los vehículos. Incluye campos privados paralicensePlate(String),brand(String),dailyRate(double) ystatus(RentalStatus, inicializado en AVAILABLE). El constructor recibe licensePlate, brand y dailyRate. Incluye los getters apropiados y un setter para status. Declara un método abstractogetVehicleType()que devuelva un String. Implementa un métodogetDetails()que devuelva"[licensePlate] [brand] ([vehicleType]) - $[dailyRate]/day - [status description]", con dailyRate formateado con 2 decimales.Car.java: Crea una clase que extienda Vehicle e implemente Rentable. Añade un campo privadoseats(int). El constructor recibe licensePlate, brand, dailyRate y seats. ImplementagetVehicleType()para que devuelva"Car". Pararent(), si el estado es AVAILABLE, establécelo en RENTED y devuelve true; de lo contrario, devuelve false. ParareturnVehicle(), si el estado es RENTED, establécelo en AVAILABLE y devuelve true; de lo contrario, devuelve false. ParacalculateCost(int days), devuelve dailyRate multiplicado por days.Motorcycle.java: Crea una clase que extienda Vehicle e implemente Rentable. Añade un campo privadoengineCC(int). El constructor recibe licensePlate, brand, dailyRate y engineCC. ImplementagetVehicleType()para que devuelva"Motorcycle". Implementa los métodos de Rentable de la misma manera que en Car, perocalculateCost()debe aplicar un descuento del 10 % (multiplicar por 0.9).RentalAgency.java: Crea una clase que administre la flota de vehículos mediante un ArrayList. Incluye los métodos:addVehicle(Vehicle vehicle): añade un vehículo a la flotafindVehicle(String licensePlate): devuelve el Vehicle o nullrentVehicle(String licensePlate, int days): busca el vehículo, intenta alquilarlo (convirtiéndolo a Rentable) y devuelve el coste del alquiler. LanzaVehicleNotAvailableExceptionsi no se encuentra el vehículo o si rent() devuelve falsereturnVehicle(String licensePlate): busca y devuelve el vehículo, devolviendo true si la operación tiene éxitogetAvailableVehicles(): devuelve un ArrayList de vehículos con estado AVAILABLE
Main.java: ¡Construye tu servicio de alquiler! Recibirás una cadena de comandos separados por comas:ADD_CAR:licensePlate:brand:dailyRate:seatsADD_MOTORCYCLE:licensePlate:brand:dailyRate:engineCCRENT:licensePlate:daysRETURN:licensePlateAVAILABLE
Procesa cada comando e imprime:
- ADD_CAR/ADD_MOTORCYCLE:
Added: [brand] ([vehicleType]) - RENT:
Rented [licensePlate] for [days] days - Total: $[cost](coste con 2 decimales), oError: [exception message] - RETURN:
Returned: [licensePlate]oReturn failed: [licensePlate] - AVAILABLE: Imprime
Available vehicles:seguido de los detalles de cada vehículo disponible en líneas separadas
Después de todos los comandos, imprime
--- Fleet Summary ---seguido de los detalles de cada vehículo.
Recibirás una entrada: la cadena de comandos separados por comas.
Por ejemplo, con la entrada ADD_CAR:ABC-123:Toyota:50.00:5,ADD_MOTORCYCLE:XYZ-789:Honda:40.00:600,RENT:ABC-123:3,RENT:ABC-123:2,AVAILABLE,RETURN:ABC-123, tu salida sería:
Added: Toyota (Car)
Added: Honda (Motorcycle)
Rented ABC-123 for 3 days - Total: $150.00
Error: Vehicle not available: ABC-123
Available vehicles:
XYZ-789 Honda (Motorcycle) - $40.00/day - ready to rent
Returned: ABC-123
--- Fleet Summary ---
ABC-123 Toyota (Car) - $50.00/day - ready to rent
XYZ-789 Honda (Motorcycle) - $40.00/day - ready to rent¡Este desafío combina la herencia (jerarquía de Vehicle), las interfaces (Rentable), los enums (RentalStatus), las excepciones personalizadas, el polimorfismo (tratar distintos tipos de vehículos de manera uniforme) y la composición (RentalAgency administrando vehículos) en un sistema completo de alquiler de vehículos!
Pruébalo tú mismo
import java.util.Scanner;
import java.util.ArrayList;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
// TODO: Crear una instancia de RentalAgency
// TODO: Dividir la entrada por comas para obtener los comandos individuales
// TODO: Procesar cada comando:
// ADD_CAR:licensePlate:brand:dailyRate:seats -> imprimir "Added: [brand] ([vehicleType])"
// ADD_MOTORCYCLE:licensePlate:brand:dailyRate:engineCC -> imprimir "Added: [brand] ([vehicleType])"
// RENT:licensePlate:days -> imprimir "Rented [licensePlate] for [days] days - Total: $[cost]" (2 decimales)
// o "Error: [exception message]" si se lanza una excepción
// RETURN:licensePlate -> imprimir "Returned: [licensePlate]" o "Return failed: [licensePlate]"
// AVAILABLE -> imprimir "Available vehicles:" seguido de los detalles de cada vehículo disponible
// TODO: Después de todos los comandos, imprimir "--- Fleet Summary ---"
// seguido de los detalles de cada vehículo
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosIntroducción a la OOPClases vs. ObjetosLa palabra clave thisMétodosCampos (Atributos)Método constructorSobrecarga de constructoresResumen - Calculadora simple4Herencia
Herencia básica (extends)La palabra clave superSobrescritura de métodos (@Override)Encadenamiento de constructoresLa clase ObjectHerencia simple y multinivelPor qué no hay herencia múltiple de clasesResumen - Jerarquía de empleados7Métodos especiales y la clase Object
Método toString()equals() y hashCode()Método clone()compareTo() y ComparableInterfaz ComparatorResumen - Ordenamiento personalizado2Modificadores de acceso y encapsulamiento
Visión general de los niveles de accesoMétodos Getter y SetterOcultamiento de informaciónLa palabra clave finalResumen - Gestor de cuentas bancarias5Polimorfismo
Fundamentos de sobrecarga de métodosSobrescritura de métodos (tiempo de ejecución)Upcasting y DowncastingEl operador instanceofClases y métodos abstractosResumen - Calculadora de figuras8Conceptos avanzados de POO
Composición vs. HerenciaAgregación vs. ComposiciónClases internas, anidadas y anónimasEnums y métodos de EnumRecords (Java 16+)Clases selladas (Java 17+)11Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón BuilderPatrón ObserverPatrón Strategy14Desafíos finales
Plataforma de E-LearningSistema bancarioDesarrollo de personajes de videojuegosServicio de alquiler de vehículos3Propiedades de clase y miembros estáticos
Variables de instancia vs. estáticasMétodos estáticosBloques estáticosConstantes (static final)Repaso - Contador y utilidad6Interfaces y Clases Abstractas
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesMétodos Default y Static en InterfacesClases Abstractas vs InterfacesInterfaces FuncionalesResumen - Sistema de Pagos9Genéricos
Introducción a los genéricosClases genéricasMétodos genéricosParámetros de tipo delimitadosComodines (?, extends, super)Resumen - Contenedor genérico12Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón IteratorPractica por tu cuenta: Compilador de Java online