Menu
Coddy logo textTech

Servicio de alquiler de vehículos

Parte de la sección Programación Orientada a Objetos del Journey de C# de Coddy. Lección 70 de 70.

challenge icon

Desafío

Fácil

¡Construyamos un servicio de alquiler de vehículos que reúna la herencia, las interfaces y el patrón Strategy! Crearás un sistema en el que se puedan alquilar distintos tipos de vehículos mediante estrategias de precios flexibles, demostrando cómo la POO permite una lógica empresarial mantenible y extensible.

Organizarás tu código en seis archivos:

  • Vehicle.cs: Crea tu jerarquía de vehículos en el espacio de nombres Rental.Models. La clase base Vehicle debe tener propiedades de solo lectura LicensePlate y Brand, una propiedad DailyRate (decimal) y una propiedad IsAvailable con un setter privado controlado mediante los métodos MarkAsRented() y MarkAsReturned(). Después, crea tres clases derivadas: Car con una propiedad Seats, Motorcycle con una propiedad EngineCC y Truck con una propiedad CargoCapacity (decimal). Cada clase derivada debe llamar al constructor base y establecer su propiedad única.
  • IPricingStrategy.cs: Define la interfaz IPricingStrategy en el espacio de nombres Rental.Pricing con un único método CalculatePrice(Vehicle vehicle, int days) que devuelve un decimal.
  • PricingStrategies.cs: Implementa dos estrategias de precios en el espacio de nombres Rental.Pricing. StandardPricing simplemente multiplica la tarifa diaria del vehículo por el número de días. WeekendDiscountPricing aplica un descuento del 10 % (multiplica por 0.9) si el alquiler es de 2 días o más; de lo contrario, utiliza el cálculo estándar.
  • RentalRecord.cs: Crea una clase Rental en el espacio de nombres Rental.Models para realizar el seguimiento de los alquileres. Debe tener propiedades de solo lectura para CustomerName (string), Vehicle (Vehicle), Days (int) y TotalPrice (decimal), todas establecidas mediante el constructor.
  • RentalService.cs: Crea una clase RentalService en el espacio de nombres Rental.Services que administre la flota y procese los alquileres. Recibe un IPricingStrategy mediante su constructor (inyección de dependencias). Implementa:
    • AddVehicle(Vehicle vehicle): añade un vehículo a la flota
    • RentVehicle(string customerName, string licensePlate, int days): devuelve un objeto Rental si el vehículo existe y está disponible; de lo contrario, devuelve null. Recuerda marcar el vehículo como alquilado y calcular el precio utilizando la estrategia inyectada.
    • ReturnVehicle(string licensePlate): marca el vehículo como disponible y devuelve true si la operación se realiza correctamente
    • GetAvailableVehicles(): devuelve una lista de todos los vehículos disponibles
  • Program.cs: Integra todo creando vehículos, configurando el servicio con una estrategia de precios y procesando las operaciones de alquiler basadas en la entrada.

Recibirás las siguientes entradas:

  • Estrategia de precios que se utilizará (standard o weekend)
  • Número de vehículos que se añadirán
  • Para cada vehículo: tipo (car, motorcycle o truck), matrícula, marca, tarifa diaria y valor específico del tipo (asientos, engineCC o capacidad de carga)
  • Número de operaciones que se realizarán
  • Para cada operación: la acción seguida de los datos relevantes

Formatos de las operaciones:

rent
{customerName}
{licensePlate}
{days}

return
{licensePlate}

available

Formatos de salida:

  • Alquiler exitoso: Rented: {Brand} ({LicensePlate}) to {CustomerName} for {Days} days - Total: {TotalPrice}
  • Alquiler fallido: Rental failed: {licensePlate}
  • Devolución exitosa: Returned: {licensePlate}
  • Devolución fallida: Return failed: {licensePlate}
  • Disponibles: imprime cada vehículo disponible como {Type}: {Brand} ({LicensePlate}) - {DailyRate}/day, donde Type es "Car", "Motorcycle" o "Truck"

Por ejemplo, si las entradas son:

weekend
3
car
ABC-123
Toyota
50
5
motorcycle
XYZ-789
Honda
30
600
truck
TRK-001
Ford
80
2000
5
available
rent
Alice
ABC-123
3
rent
Bob
ABC-123
2
available
return
ABC-123

La salida debe ser:

Car: Toyota (ABC-123) - 50/day
Motorcycle: Honda (XYZ-789) - 30/day
Truck: Ford (TRK-001) - 80/day
Rented: Toyota (ABC-123) to Alice for 3 days - Total: 135.0
Rental failed: ABC-123
Motorcycle: Honda (XYZ-789) - 30/day
Truck: Ford (TRK-001) - 80/day
Returned: ABC-123

Observa cómo la estrategia de precios se inyecta en el servicio: podrías cambiar fácilmente StandardPricing por WeekendDiscountPricing sin modificar en absoluto el código de RentalService. ¡Este es el poder del patrón Strategy combinado con la inyección de dependencias!

Pruébalo tú mismo

using System;
using System.Collections.Generic;
using Rental.Models;
using Rental.Pricing;
using Rental.Services;

class Program
{
    public static void Main(string[] args)
    {
        // Leer el tipo de estrategia de precios
        string strategyType = Console.ReadLine();
        
        // TODO: Crear la estrategia de precios adecuada basada en la entrada
        // "standard" -> StandardPricing
        // "weekend" -> WeekendDiscountPricing
        IPricingStrategy strategy = null; // TODO: Inicializar basado en strategyType
        
        // TODO: Crear RentalService con la estrategia de precios
        
        // Leer el número de vehículos
        int vehicleCount = Convert.ToInt32(Console.ReadLine());
        
        // TODO: Leer y añadir cada vehículo al servicio
        // Para cada vehículo, leer:
        // - tipo (car, motorcycle, truck)
        // - matrícula
        // - marca
        // - tarifa diaria
        // - valor específico del tipo (seats, engineCC o capacidad de carga)
        
        // Leer el número de operaciones
        int operationCount = Convert.ToInt32(Console.ReadLine());
        
        // TODO: Procesar cada operación
        // Operaciones: rent, return, available
        // 
        // Para "rent":
        //   Leer customerName, licensePlate, days
        //   Salida: "Rented: {Brand} ({LicensePlate}) to {CustomerName} for {Days} days - Total: {TotalPrice}"
        //   O: "Rental failed: {licensePlate}"
        //
        // Para "return":
        //   Leer licensePlate
        //   Salida: "Returned: {licensePlate}" o "Return failed: {licensePlate}"
        //
        // Para "available":
        //   Muestra cada vehículo disponible como:
        //   "{Type}: {Brand} ({LicensePlate}) - {DailyRate}/day"
    }
}

Todas las lecciones de Programación Orientada a Objetos

Practica por tu cuenta: Compilador de C# online