Service de location de véhicules
Fait partie de la section Programmation Orientée Objet du Journey Java de Coddy — leçon 87 sur 87.
Pour ce défi final, vous allez construire un système de Service de Location de Véhicules qui regroupe tous les concepts de la POO que vous avez maîtrisés tout au long de ce cours.
Votre système doit modéliser une flotte de différents types de véhicules. Considérez une classe de base Vehicle avec des propriétés communes telles que la plaque d'immatriculation, la marque et le tarif de location journalier. Des sous-classes telles que Car, Motorcycle et Truck peuvent étendre cela avec des attributs spécifiques comme le nombre de sièges, la cylindrée du moteur ou la capacité de chargement.
Les interfaces peuvent définir des comportements de location : une interface Rentable pourrait déclarer des méthodes comme rent(), returnVehicle() et calculateCost(int days). Différents types de véhicules pourraient implémenter des stratégies de tarification différemment, ce qui en fait un cas d'utilisation parfait pour le polymorphisme.
Réfléchissez à la manière dont une classe RentalAgency gère la flotte en utilisant la composition.
Les exceptions personnalisées comme VehicleNotAvailableException peuvent gérer les cas particuliers.
Vous pourriez appliquer le pattern Factory pour créer des véhicules ou utiliser des enums pour les catégories de véhicules et le statut de location.
Ce défi teste votre capacité à concevoir un système POO complet et bien structuré. Bonne chance !
Défi
FacileConstruisons un service complet de location de véhicules qui rassemble tout ce que vous avez appris sur la POO ! Vous allez créer un système qui gère une flotte de différents types de véhicules, gère les locations avec une validation appropriée et utilise un modèle de fabrique pour créer des véhicules.
Vous organiserez votre code sur sept fichiers :
RentalStatus.java: Créez un enum représentant le statut de location d'un véhicule. Incluez les valeursAVAILABLE,RENTEDetMAINTENANCE. Ajoutez un champ privédescription(String), un constructeur et un getter.AVAILABLEdoit avoir la description "ready to rent",RENTEDdoit avoir "currently in use" etMAINTENANCEdoit avoir "under service".VehicleNotAvailableException.java: Créez une exception personnalisée qui étendException. Le constructeur doit accepter une plaque d'immatriculation et créer un message au formatVehicle not available: [licensePlate].Rentable.java: Créez une interface définissant les opérations de location. Déclarez les méthodesrent()retournant un boolean,returnVehicle()retournant un boolean etcalculateCost(int days)retournant un double.Vehicle.java: Créez une classe de base abstraite pour tous les véhicules. Incluez des champs privés pourlicensePlate(String),brand(String),dailyRate(double) etstatus(RentalStatus, initialisé àAVAILABLE). Le constructeur prendlicensePlate,brandetdailyRate. Incluez les getters appropriés et un setter pourstatus. Déclarez une méthode abstraitegetVehicleType()retournant une String. Implémentez une méthodegetDetails()qui retourne"[licensePlate] [brand] ([vehicleType]) - $[dailyRate]/day - [status description]"avecdailyRateformaté à 2 décimales.Car.java: Créez une classe étendantVehicleet implémentantRentable. Ajoutez un champ privéseats(int). Le constructeur prendlicensePlate,brand,dailyRateetseats. ImplémentezgetVehicleType()pour retourner"Car". Pourrent(), si le statut estAVAILABLE, réglez-le surRENTEDet retourneztrue; sinon retournezfalse. PourreturnVehicle(), si le statut estRENTED, réglez-le surAVAILABLEet retourneztrue; sinon retournezfalse. PourcalculateCost(int days), retournezdailyRatemultiplié pardays.Motorcycle.java: Créez une classe étendantVehicleet implémentantRentable. Ajoutez un champ privéengineCC(int). Le constructeur prendlicensePlate,brand,dailyRateetengineCC. ImplémentezgetVehicleType()pour retourner"Motorcycle". Implémentez les méthodes deRentablede la même manière que pourCar, maiscalculateCost()doit appliquer une remise de 10 % (multiplier par0.9).RentalAgency.java: Créez une classe qui gère la flotte de véhicules à l'aide d'uneArrayList. Incluez les méthodes :addVehicle(Vehicle vehicle)- ajoute un véhicule à la flottefindVehicle(String licensePlate)- retourne leVehicleounullrentVehicle(String licensePlate, int days)- trouve le véhicule, tente de le louer (en le castant enRentable) et retourne le coût de la location. LancezVehicleNotAvailableExceptionsi le véhicule n'est pas trouvé ou sirent()retournefalsereturnVehicle(String licensePlate)- trouve et retourne le véhicule, retournanttrueen cas de succèsgetAvailableVehicles()- retourne uneArrayListde véhicules ayant le statutAVAILABLE
Main.java: Construisez votre service de location ! Vous recevrez une chaîne de commandes séparées par des virgules :ADD_CAR:licensePlate:brand:dailyRate:seatsADD_MOTORCYCLE:licensePlate:brand:dailyRate:engineCCRENT:licensePlate:daysRETURN:licensePlateAVAILABLE
Traitez chaque commande et affichez :
ADD_CAR/ADD_MOTORCYCLE:Added: [brand] ([vehicleType])RENT:Rented [licensePlate] for [days] days - Total: $[cost](coût à 2 décimales), ouError: [exception message]RETURN:Returned: [licensePlate]ouReturn failed: [licensePlate]AVAILABLE: AffichezAvailable vehicles:suivi des détails de chaque véhicule disponible sur des lignes séparées
Après toutes les commandes, affichez
--- Fleet Summary ---suivi des détails de chaque véhicule.
Vous recevrez une seule entrée : la chaîne de commande séparée par des virgules.
Par exemple, avec l'entrée 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, votre sortie serait :
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 rentCe défi combine l'héritage (hiérarchie Vehicle), les interfaces (Rentable), les enums (RentalStatus), les exceptions personnalisées, le polymorphisme (traiter uniformément différents types de véhicules) et la composition (RentalAgency gérant les véhicules) dans un système complet de service de location !
Aide-mémoire
Ce défi final combine plusieurs concepts de la POO dans un système complet. Voici les principaux modèles et techniques :
Énumérations avec des champs
Les énumérations peuvent avoir des champs, des constructeurs et des méthodes :
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;
}
}Exceptions personnalisées
Créez des exceptions spécifiques au domaine en étendant Exception :
public class VehicleNotAvailableException extends Exception {
public VehicleNotAvailableException(String licensePlate) {
super("Vehicle not available: " + licensePlate);
}
}Classes de base abstraites avec interfaces
Combinez des classes abstraites pour une implémentation partagée avec des interfaces pour les contrats de comportement :
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;
}
}Composition pour la gestion
Utilisez la composition pour gérer des collections d'objets :
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);
}
}Le polymorphisme en action
Différentes sous-classes peuvent implémenter les méthodes d'interface différemment :
// Car : tarification standard
public double calculateCost(int days) {
return dailyRate * days;
}
// Motorcycle : tarification avec remise
public double calculateCost(int days) {
return dailyRate * days * 0.9;
}Essayez vous-même
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: Créer une instance de RentalAgency
// TODO: Diviser l'entrée par des virgules pour obtenir les commandes individuelles
// TODO: Traiter chaque commande :
// ADD_CAR:licensePlate:brand:dailyRate:seats -> afficher "Added: [brand] ([vehicleType])"
// ADD_MOTORCYCLE:licensePlate:brand:dailyRate:engineCC -> afficher "Added: [brand] ([vehicleType])"
// RENT:licensePlate:days -> afficher "Rented [licensePlate] for [days] days - Total: $[cost]" (2 décimales)
// ou "Error: [exception message]" si une exception est levée
// RETURN:licensePlate -> afficher "Returned: [licensePlate]" ou "Return failed: [licensePlate]"
// AVAILABLE -> afficher "Available vehicles:" suivi des détails de chaque véhicule disponible
// TODO: Après toutes les commandes, afficher "--- Fleet Summary ---"
// suivi des détails de chaque véhicule
}
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesChamps (Attributs)Méthode constructeurSurcharge de constructeurRécapitulatif - Calculatrice simple4Héritage
Héritage de base (extends)Le mot-clé superRedéfinition de méthode (@Override)Chaînage de constructeursLa classe ObjectHéritage simple et multiniveauPourquoi pas d'héritage multiple de classesRécapitulatif - Hiérarchie des employés7Méthodes spéciales et classe Object
Méthode toString()equals() et hashCode()Méthode clone()compareTo() et ComparableInterface ComparatorRécapitulatif - Tri personnalisé2Modificateurs d'accès et Encapsulation
Aperçu des niveaux d'accèsMéthodes Getter et SetterMasquage d'informationsLe mot-clé finalRécapitulatif - Gestionnaire de compte bancaire5Polymorphisme
Bases de la surcharge de méthodesRedéfinition de méthodes (Run-Time)Upcasting et DowncastingL'opérateur instanceofClasses et méthodes abstraitesRécapitulatif - Calculateur de formes8Concepts avancés de la POO
Composition vs HéritageAgrégation vs CompositionClasses internes, imbriquées et anonymesEnums et méthodes d'EnumRecords (Java 16+)Classes scellées (Java 17+)11Patrons de conception, partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron MonteurPatron ObservateurPatron Stratégie14Défis finaux
Plateforme d'E-LearningSystème bancaireDéveloppement de personnages de jeuService de location de véhicules3Propriétés de classe et membres statiques
Variables d'instance vs variables statiquesMéthodes statiquesBlocs statiquesConstantes (static final)Récapitulatif - Compteur et utilitaire6Interfaces et Classes Abstraites
Introduction aux InterfacesImplémentation d'InterfacesImplémentation d'Interfaces MultiplesDefault et Static dans les InterfacesClasses Abstraites vs InterfacesInterfaces FonctionnellesRécapitulatif - Système de Paiement9La généricité
Introduction à la généricitéClasses génériquesMéthodes génériquesParamètres de type bornésWildcards (?, extends, super)Récapitulatif - Conteneur générique12Patrons de conception, partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Template MethodPatron ÉtatPatron CompositePatron Itérateur