Menu
Coddy logo textTech

Vehicle Rental Service

Part of the Object Oriented Programming section of Coddy's C# journey — lesson 70 of 70.

challenge icon

Challenge

Easy

Let's build a vehicle rental service that brings together inheritance, interfaces, and the Strategy pattern! You'll create a system where different vehicle types can be rented using flexible pricing strategies - demonstrating how OOP enables maintainable, extensible business logic.

You'll organize your code across six files:

  • Vehicle.cs: Create your vehicle hierarchy in the Rental.Models namespace. The base Vehicle class should have read-only LicensePlate and Brand properties, a DailyRate (decimal), and an IsAvailable property with a private setter controlled through MarkAsRented() and MarkAsReturned() methods. Then create three derived classes: Car with a Seats property, Motorcycle with an EngineCC property, and Truck with a CargoCapacity (decimal) property. Each derived class should call the base constructor and set its unique property.
  • IPricingStrategy.cs: Define the IPricingStrategy interface in the Rental.Pricing namespace with a single method CalculatePrice(Vehicle vehicle, int days) that returns a decimal.
  • PricingStrategies.cs: Implement two pricing strategies in the Rental.Pricing namespace. StandardPricing simply multiplies the vehicle's daily rate by the number of days. WeekendDiscountPricing applies a 10% discount (multiply by 0.9) if the rental is for 2 or more days, otherwise uses the standard calculation.
  • RentalRecord.cs: Create a Rental class in the Rental.Models namespace to track rentals. It should have read-only properties for CustomerName (string), Vehicle (Vehicle), Days (int), and TotalPrice (decimal), all set through the constructor.
  • RentalService.cs: Create a RentalService class in the Rental.Services namespace that manages the fleet and processes rentals. It receives an IPricingStrategy through its constructor (dependency injection). Implement:
    • AddVehicle(Vehicle vehicle) - adds a vehicle to the fleet
    • RentVehicle(string customerName, string licensePlate, int days) - returns a Rental object if the vehicle exists and is available, otherwise returns null. Remember to mark the vehicle as rented and calculate the price using the injected strategy.
    • ReturnVehicle(string licensePlate) - marks the vehicle as available, returns true if successful
    • GetAvailableVehicles() - returns a list of all available vehicles
  • Program.cs: Bring everything together by creating vehicles, setting up the service with a pricing strategy, and processing rental operations based on input.

You will receive the following inputs:

  • Pricing strategy to use (standard or weekend)
  • Number of vehicles to add
  • For each vehicle: type (car, motorcycle, or truck), license plate, brand, daily rate, and type-specific value (seats, engineCC, or cargo capacity)
  • Number of operations to perform
  • For each operation: the action followed by relevant data

Operation formats:

rent
{customerName}
{licensePlate}
{days}

return
{licensePlate}

available

Output formats:

  • Rent success: Rented: {Brand} ({LicensePlate}) to {CustomerName} for {Days} days - Total: {TotalPrice}
  • Rent failure: Rental failed: {licensePlate}
  • Return success: Returned: {licensePlate}
  • Return failure: Return failed: {licensePlate}
  • Available: Print each available vehicle as {Type}: {Brand} ({LicensePlate}) - {DailyRate}/day where Type is "Car", "Motorcycle", or "Truck"

For example, if the inputs are:

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

The output should be:

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

Notice how the pricing strategy is injected into the service - you could easily swap StandardPricing for WeekendDiscountPricing without changing the RentalService code at all. This is the power of the Strategy pattern combined with dependency injection!

Try it yourself

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

class Program
{
    public static void Main(string[] args)
    {
        // Read pricing strategy type
        string strategyType = Console.ReadLine();
        
        // TODO: Create the appropriate pricing strategy based on input
        // "standard" -> StandardPricing
        // "weekend" -> WeekendDiscountPricing
        IPricingStrategy strategy = null; // TODO: Initialize based on strategyType
        
        // TODO: Create RentalService with the pricing strategy
        
        // Read number of vehicles
        int vehicleCount = Convert.ToInt32(Console.ReadLine());
        
        // TODO: Read and add each vehicle to the service
        // For each vehicle, read:
        // - type (car, motorcycle, truck)
        // - license plate
        // - brand
        // - daily rate
        // - type-specific value (seats, engineCC, or cargo capacity)
        
        // Read number of operations
        int operationCount = Convert.ToInt32(Console.ReadLine());
        
        // TODO: Process each operation
        // Operations: rent, return, available
        // 
        // For "rent":
        //   Read customerName, licensePlate, days
        //   Output: "Rented: {Brand} ({LicensePlate}) to {CustomerName} for {Days} days - Total: {TotalPrice}"
        //   Or: "Rental failed: {licensePlate}"
        //
        // For "return":
        //   Read licensePlate
        //   Output: "Returned: {licensePlate}" or "Return failed: {licensePlate}"
        //
        // For "available":
        //   Output each available vehicle as:
        //   "{Type}: {Brand} ({LicensePlate}) - {DailyRate}/day"
    }
}

All lessons in Object Oriented Programming