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.
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 nombresRental.Models. La clase baseVehicledebe tener propiedades de solo lecturaLicensePlateyBrand, unaDailyRate(decimal) y una propiedadIsAvailablecon un setter privado controlado a través de los métodosMarkAsRented()yMarkAsReturned(). Luego, crea tres clases derivadas:Carcon una propiedadSeats,Motorcyclecon una propiedadEngineCCyTruckcon una propiedadCargoCapacity(decimal). Cada clase derivada debe llamar al constructor base y establecer su propiedad única.IPricingStrategy.cs: Define la interfazIPricingStrategyen el espacio de nombresRental.Pricingcon un único métodoCalculatePrice(Vehicle vehicle, int days)que devuelva un decimal.PricingStrategies.cs: Implementa dos estrategias de precios en el espacio de nombresRental.Pricing.StandardPricingsimplemente multiplica la tarifa diaria del vehículo por el número de días.WeekendDiscountPricingaplica 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 claseRentalen el espacio de nombresRental.Modelspara rastrear los alquileres. Debe tener propiedades de solo lectura paraCustomerName(string),Vehicle(Vehicle),Days(int) yTotalPrice(decimal), todas establecidas a través del constructor.RentalService.cs: Crea una claseRentalServiceen el espacio de nombresRental.Servicesque gestione la flota y procese los alquileres. Recibe unaIPricingStrategya través de su constructor (inyección de dependencias). Implementa:AddVehicle(Vehicle vehicle)- añade un vehículo a la flotaRentVehicle(string customerName, string licensePlate, int days)- devuelve un objetoRentalsi el vehículo existe y está disponible; de lo contrario, devuelvenull. Recuerda marcar el vehículo como alquilado y calcular el precio utilizando la estrategia inyectada.ReturnVehicle(string licensePlate)- marca el vehículo como disponible, devuelvetruesi tiene éxitoGetAvailableVehicles()- 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 (
standardoweekend) - Número de vehículos a añadir
- Para cada vehículo: tipo (
car,motorcycleotruck), 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}
availableFormatos 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}/daydonde 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-123La 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-123Observa 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
1Fundamentos de OOP
Archivos externosNamespaces y directivasIntro a clases y objetosLa palabra clave 'this'Métodos y parámetrosCampos vs PropiedadesConstructoresInicializadores de objetosResumen - Calculadora simple4Herencia
Sintaxis básica de herencia (:)La palabra clave 'base'Palabras clave Virtual y OverrideClases selladas (Sealed)La clase base 'object'Resumen: Jerarquía de empleados7Características avanzadas
Sobrecarga de operadoresIndexadores (this[])Sobrescritura de ToString()Métodos de extensiónResumen - Lista personalizada10Patrones de diseño - Parte 1
Introducción a los patrones de diseñoSingleton Thread-SafePatrón FactoryPatrón Observer (Eventos)Patrón Strategy13Desafíos finales
Plataforma de e-learningComponente de personaje de juegoServicio de alquiler de vehículos2Propiedades y miembros estáticos
Propiedades autoimplementadasPropiedades de solo lectura y escrituraCampos y métodos estáticosClases estáticasMiembros con cuerpo de expresión5Polimorfismo e Interfaces
Polimorfismo: Compilación vs. EjecuciónInterfaz vs. Clase AbstractaInterfaces MúltiplesInterfaces ExplícitasUpcasting y DowncastingRepaso: Calculadora de Figuras8Conceptos avanzados de POO
Composición sobre herenciaGenéricos (clases y métodos)Delegados y eventosAtributos y ReflexiónIDisposable y la sentencia usingFundamentos de Inyección de dependencias11Patrones de diseño, parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón Composite3Arquitectura de clases
Datos de instancia vs. estáticosPalabras clave 'readonly' y 'const'Campos de respaldoResumen - Gestor de cuentas bancarias6Encapsulamiento
Modificadores de accesoPropiedades para el encapsulamientoImplementación de ocultamiento de datosPatrones de inmutabilidadRepaso - Registros de estudiantes