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

¡Vamos a construir un servicio de alquiler de vehículos que reúna herencia, interfaces y el patrón Strategy! Crearás un sistema donde diferentes tipos de vehículos pueden ser alquilados utilizando estrategias de precios flexibles, demostrando cómo la POO permite una lógica de negocio 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 DailyRate (decimal) y una propiedad IsAvailable con un setter privado controlado a través de los métodos MarkAsRented() y MarkAsReturned(). Luego, 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 devuelva 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% (multiplicar por 0.9) si el alquiler es por 2 o más días; de lo contrario, utiliza el cálculo estándar.
  • RentalRecord.cs: Crea una clase Rental en el espacio de nombres Rental.Models para rastrear los alquileres. Debe tener propiedades de solo lectura para CustomerName (string), Vehicle (Vehicle), Days (int) y TotalPrice (decimal), todas establecidas a través del constructor.
  • RentalService.cs: Crea una clase RentalService en el espacio de nombres Rental.Services que gestione la flota y procese los alquileres. Recibe una IPricingStrategy a través de 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, devuelve true si tiene éxito
    • GetAvailableVehicles() - devuelve una lista de todos los vehículos disponibles
  • Program.cs: Une 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 a utilizar (standard o weekend)
  • Número de vehículos a añadir
  • 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 a realizar
  • Para cada operación: la acción seguida de los datos relevantes

Formatos de operación:

rent
{customerName}
{licensePlate}
{days}

return
{licensePlate}

available

Formatos de salida:

  • Éxito de alquiler: Rented: {Brand} ({LicensePlate}) to {CustomerName} for {Days} days - Total: {TotalPrice}
  • Fallo de alquiler: Rental failed: {licensePlate}
  • Éxito de devolución: Returned: {licensePlate}
  • Fallo de devolución: 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 debería 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
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 cambiar 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:
        // - type (car, motorcycle, truck)
        // - license plate
        // - brand
        // - daily rate
        // - valor específico del tipo (seats, engineCC, o cargo capacity)
        
        // 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":
        //   Mostrar cada vehículo disponible como:
        //   "{Type}: {Brand} ({LicensePlate}) - {DailyRate}/day"
    }
}

Todas las lecciones de Programación Orientada a Objetos