Serviço de Aluguel de Veículos
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy — lição 87 de 87.
Para este desafio final, você construirá um sistema de Serviço de Aluguel de Veículos que reúne todos os conceitos de POO que você dominou ao longo deste curso.
Seu sistema deve modelar uma frota de diferentes tipos de veículos. Considere uma classe base Vehicle com propriedades comuns como placa, marca e valor da diária de aluguel. Subclasses como Car, Motorcycle e Truck podem estender isso com atributos específicos como número de assentos, cilindrada ou capacidade de carga.
Interfaces podem definir comportamentos de aluguel: uma interface Rentable pode declarar métodos como rent(), returnVehicle() e calculateCost(int days). Diferentes tipos de veículos podem implementar estratégias de precificação de forma diferente, tornando este um caso de uso perfeito para o polimorfismo.
Pense em como uma classe RentalAgency gerencia a frota usando composição.
Exceções personalizadas como VehicleNotAvailableException podem lidar com casos extremos.
Você pode aplicar o padrão Factory para criar veículos ou usar enums para categorias de veículos e status de aluguel.
Este desafio testa sua habilidade de projetar um sistema OOP completo e bem estruturado. Boa sorte!
Desafio
FácilVamos construir um Serviço de Aluguel de Veículos completo que reúne tudo o que você aprendeu sobre POO! Você criará um sistema que gerencia uma frota de diferentes tipos de veículos, lida com aluguéis com a validação adequada e usa um padrão de fábrica para criar veículos.
Você organizará seu código em sete arquivos:
RentalStatus.java: Crie um enum representando o status de aluguel de um veículo. Inclua os valoresAVAILABLE,RENTEDeMAINTENANCE. Adicione um campo privadodescription(String), um construtor e um getter.AVAILABLEdeve ter a descrição "ready to rent",RENTEDdeve ter "currently in use" eMAINTENANCEdeve ter "under service".VehicleNotAvailableException.java: Crie uma exceção personalizada que estendeException. O construtor deve aceitar uma placa (license plate) e criar uma mensagem no formatoVehicle not available: [licensePlate].Rentable.java: Crie uma interface definindo as operações de aluguel. Declare os métodosrent()retornando um boolean,returnVehicle()retornando um boolean ecalculateCost(int days)retornando um double.Vehicle.java: Crie uma classe base abstrata para todos os veículos. Inclua campos privados paralicensePlate(String),brand(String),dailyRate(double) estatus(RentalStatus, inicializado comoAVAILABLE). O construtor recebelicensePlate,brandedailyRate. Inclua os getters apropriados e um setter parastatus. Declare um método abstratogetVehicleType()retornando uma String. Implemente um métodogetDetails()que retorna"[licensePlate] [brand] ([vehicleType]) - $[dailyRate]/day - [status description]"comdailyRateformatado para 2 casas decimais.Car.java: Crie uma classe estendendoVehiclee implementandoRentable. Adicione um campo privadoseats(int). O construtor recebelicensePlate,brand,dailyRateeseats. ImplementegetVehicleType()para retornar"Car". Pararent(), se o status forAVAILABLE, defina-o comoRENTEDe retorne true; caso contrário, retorne false. ParareturnVehicle(), se o status forRENTED, defina-o comoAVAILABLEe retorne true; caso contrário, retorne false. ParacalculateCost(int days), retornedailyRatevezesdays.Motorcycle.java: Crie uma classe estendendoVehiclee implementandoRentable. Adicione um campo privadoengineCC(int). O construtor recebelicensePlate,brand,dailyRateeengineCC. ImplementegetVehicleType()para retornar"Motorcycle". Implemente os métodos deRentableda mesma forma queCar, mascalculateCost()deve aplicar um desconto de 10% (multiplicar por 0.9).RentalAgency.java: Crie uma classe que gerencia a frota de veículos usando umArrayList. Inclua os métodos:addVehicle(Vehicle vehicle)- adiciona um veículo à frotafindVehicle(String licensePlate)- retorna oVehicleou nullrentVehicle(String licensePlate, int days)- encontra o veículo, tenta alugá-lo (fazendo o cast paraRentable) e retorna o custo do aluguel. LanceVehicleNotAvailableExceptionse o veículo não for encontrado ou serent()retornar falsereturnVehicle(String licensePlate)- encontra e devolve o veículo, retornando true em caso de sucessogetAvailableVehicles()- retorna umArrayListde veículos com statusAVAILABLE
Main.java: Construa seu serviço de aluguel! Você receberá uma string de comandos separados por vírgula:ADD_CAR:licensePlate:brand:dailyRate:seatsADD_MOTORCYCLE:licensePlate:brand:dailyRate:engineCCRENT:licensePlate:daysRETURN:licensePlateAVAILABLE
Processe cada comando e imprima:
- ADD_CAR/ADD_MOTORCYCLE:
Added: [brand] ([vehicleType]) - RENT:
Rented [licensePlate] for [days] days - Total: $[cost](custo com 2 decimais), ouError: [exception message] - RETURN:
Returned: [licensePlate]ouReturn failed: [licensePlate] - AVAILABLE: Imprima
Available vehicles:seguido pelos detalhes de cada veículo disponível em linhas separadas
Após todos os comandos, imprima
--- Fleet Summary ---seguido pelos detalhes de cada veículo.
Você receberá uma entrada: a string de comandos separados por vírgula.
Por exemplo, com a 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, sua saída seria:
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 rentEste desafio combina herança (hierarquia Vehicle), interfaces (Rentable), enums (RentalStatus), exceções personalizadas, polimorfismo (tratando diferentes tipos de veículos uniformemente) e composição (RentalAgency gerenciando veículos) em um sistema completo de serviço de aluguel!
Folha de consulta
Este desafio final combina múltiplos conceitos de POO em um sistema completo. Aqui estão os principais padrões e técnicas:
Enums com Campos
Enums podem ter campos, construtores e métodos:
public enum RentalStatus {
AVAILABLE("ready to rent"),
RENTED("currently in use");
private String description;
private RentalStatus(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}Exceções Personalizadas
Crie exceções específicas do domínio estendendo Exception:
public class VehicleNotAvailableException extends Exception {
public VehicleNotAvailableException(String licensePlate) {
super("Vehicle not available: " + licensePlate);
}
}Classes Abstratas com Interfaces
Combine classes abstratas para implementação compartilhada com interfaces para contratos de comportamento:
public abstract class Vehicle {
private String licensePlate;
private RentalStatus status;
public abstract String getVehicleType();
public String getDetails() {
return licensePlate + " " + getVehicleType() + " - " + status.getDescription();
}
}
public interface Rentable {
boolean rent();
boolean returnVehicle();
double calculateCost(int days);
}
public class Car extends Vehicle implements Rentable {
public boolean rent() {
if (getStatus() == RentalStatus.AVAILABLE) {
setStatus(RentalStatus.RENTED);
return true;
}
return false;
}
}Composição para Gerenciamento
Use composição para gerenciar coleções de objetos:
public class RentalAgency {
private ArrayList<Vehicle> fleet = new ArrayList<>();
public void addVehicle(Vehicle vehicle) {
fleet.add(vehicle);
}
public double rentVehicle(String licensePlate, int days) throws VehicleNotAvailableException {
Vehicle vehicle = findVehicle(licensePlate);
if (vehicle == null) {
throw new VehicleNotAvailableException(licensePlate);
}
Rentable rentable = (Rentable) vehicle;
if (!rentable.rent()) {
throw new VehicleNotAvailableException(licensePlate);
}
return rentable.calculateCost(days);
}
}Polimorfismo em Ação
Diferentes subclasses podem implementar métodos de interface de forma distinta:
// Car: standard pricing
public double calculateCost(int days) {
return dailyRate * days;
}
// Motorcycle: discounted pricing
public double calculateCost(int days) {
return dailyRate * days * 0.9;
}Experimente você mesmo
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: Criar uma instância de RentalAgency
// TODO: Dividir a entrada por vírgula para obter comandos individuais
// TODO: Processar 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 casas decimais)
// ou "Error: [exception message]" se uma exceção for lançada
// RETURN:licensePlate -> imprimir "Returned: [licensePlate]" ou "Return failed: [licensePlate]"
// AVAILABLE -> imprimir "Available vehicles:" seguido pelos detalhes de cada veículo disponível
// TODO: Após todos os comandos, imprimir "--- Fleet Summary ---"
// seguido pelos detalhes de cada veículo
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosCampos (Atributos)Método ConstrutorSobrecarga de ConstrutorRecapitulação - Calculadora Simples4Herança
Herança Básica (extends)A Palavra-chave superSobrescrita de Método (@Override)Encadeamento de ConstrutoresA Classe ObjectHerança Simples e MultinívelPor que não há Herança Múltipla de ClassesRecapitulação - Hierarquia de Funcionários7Métodos Especiais e a Classe Object
Método toString()equals() e hashCode()Método clone()compareTo() e ComparableInterface ComparatorRecapitulação - Ordenação Personalizada2Modificadores de Acesso e Encapsulamento
Visão Geral dos Níveis de AcessoMétodos Getter e SetterOcultação de InformaçõesA Palavra-chave finalRecapitulação - Gerenciador de Conta Bancária5Polimorfismo
Fundamentos de Sobrecarga de MétodosSobrescrita de Métodos (Tempo de Execução)Upcasting e DowncastingO Operador instanceofClasses e Métodos AbstratosRecapitulação - Calculadora de Formas8Conceitos Avançados de OOP
Composição vs HerançaAgregação vs ComposiçãoClasses Internas, Aninhadas e AnônimasEnums e Métodos de EnumRecords (Java 16+)Classes Seladas (Java 17+)11Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão BuilderPadrão ObserverPadrão Strategy14Desafios Finais
Plataforma de E-LearningSistema BancárioDesenvolvimento de Personagens de JogosServiço de Aluguel de Veículos3Propriedades de Classe e Membros Estáticos
Variáveis de Instância vs EstáticasMétodos EstáticosBlocos EstáticosConstantes (static final)Recapitulação - Contador e Utilitário6Interfaces e Classes Abstratas
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesDefault e Static em InterfacesClasses Abstratas vs InterfacesInterfaces FuncionaisRecapitulação - Sistema de Pagamento9Generics
Introdução a GenericsClasses GenéricasMétodos GenéricosParâmetros de Tipos DelimitadosWildcards (?, extends, super)Recapitulação - Container Genérico12Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão Iterator