Menu
Coddy logo textTech

차량 대여 서비스

Coddy C# 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 70개 중 70번째.

challenge icon

챌린지

쉬움

상속, 인터페이스, 그리고 전략(Strategy) 패턴을 결합한 차량 대여 서비스를 구축해 봅시다! 유연한 가격 책정 전략을 사용하여 다양한 차량 유형을 대여할 수 있는 시스템을 만들게 됩니다. 이를 통해 객체 지향 프로그래밍(OOP)이 어떻게 유지보수가 쉽고 확장 가능한 비즈니스 로직을 가능하게 하는지 실습해 볼 것입니다.

코드는 다음 여섯 개의 파일로 구성됩니다:

  • Vehicle.cs: Rental.Models 네임스페이스에 차량 계층 구조를 만듭니다. 기본 Vehicle 클래스는 읽기 전용인 LicensePlateBrand 속성, DailyRate (decimal), 그리고 MarkAsRented()MarkAsReturned() 메서드를 통해 제어되는 private setter를 가진 IsAvailable 속성을 가져야 합니다. 그런 다음 세 개의 파생 클래스를 만듭니다: Seats 속성이 있는 Car, EngineCC 속성이 있는 Motorcycle, CargoCapacity (decimal) 속성이 있는 Truck입니다. 각 파생 클래스는 기본 생성자를 호출하고 고유한 속성을 설정해야 합니다.
  • IPricingStrategy.cs: Rental.Pricing 네임스페이스에 decimal을 반환하는 단일 메서드 CalculatePrice(Vehicle vehicle, int days)를 가진 IPricingStrategy 인터페이스를 정의합니다.
  • PricingStrategies.cs: Rental.Pricing 네임스페이스에 두 가지 가격 전략을 구현합니다. StandardPricing은 단순히 차량의 일일 요금에 대여 일수를 곱합니다. WeekendDiscountPricing은 대여 기간이 2일 이상인 경우 10% 할인(0.9를 곱함)을 적용하고, 그렇지 않으면 표준 계산 방식을 사용합니다.
  • RentalRecord.cs: 대여 기록을 추적하기 위해 Rental.Models 네임스페이스에 Rental 클래스를 만듭니다. 이 클래스는 생성자를 통해 설정되는 CustomerName (string), Vehicle (Vehicle), Days (int), TotalPrice (decimal)에 대한 읽기 전용 속성을 가져야 합니다.
  • RentalService.cs: 차량 함대를 관리하고 대여를 처리하는 RentalService 클래스를 Rental.Services 네임스페이스에 만듭니다. 이 클래스는 생성자를 통해 IPricingStrategy를 주입받습니다(의존성 주입). 다음 메서드들을 구현하세요:
    • AddVehicle(Vehicle vehicle) - 함대에 차량을 추가합니다.
    • RentVehicle(string customerName, string licensePlate, int days) - 차량이 존재하고 대여 가능한 경우 Rental 객체를 반환하고, 그렇지 않으면 null을 반환합니다. 차량을 대여 중으로 표시하고 주입된 전략을 사용하여 가격을 계산해야 함을 잊지 마세요.
    • ReturnVehicle(string licensePlate) - 차량을 대여 가능 상태로 표시하며, 성공하면 true를 반환합니다.
    • GetAvailableVehicles() - 현재 대여 가능한 모든 차량의 리스트를 반환합니다.
  • Program.cs: 차량을 생성하고, 가격 전략을 사용하여 서비스를 설정하며, 입력에 따라 대여 작업을 처리하여 모든 요소를 하나로 결합합니다.

다음 입력을 받게 됩니다:

  • 사용할 가격 전략 (standard 또는 weekend)
  • 추가할 차량의 수
  • 각 차량 정보: 유형 (car, motorcycle, 또는 truck), 번호판, 브랜드, 일일 요금, 그리고 유형별 고유 값 (좌석 수, 배기량, 또는 적재 용량)
  • 수행할 작업의 수
  • 각 작업 정보: 액션 이름과 관련 데이터

작업 형식:

rent
{customerName}
{licensePlate}
{days}

return
{licensePlate}

available

출력 형식:

  • 대여 성공: Rented: {Brand} ({LicensePlate}) to {CustomerName} for {Days} days - Total: {TotalPrice}
  • 대여 실패: Rental failed: {licensePlate}
  • 반납 성공: Returned: {licensePlate}
  • 반납 실패: Return failed: {licensePlate}
  • 대여 가능 목록: 각 대여 가능한 차량을 {Type}: {Brand} ({LicensePlate}) - {DailyRate}/day 형식으로 출력합니다. 여기서 Type은 "Car", "Motorcycle", 또는 "Truck"입니다.

예를 들어, 입력이 다음과 같다면:

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

출력은 다음과 같아야 합니다:

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

가격 전략이 서비스에 어떻게 주입되는지 주목하세요. RentalService 코드를 전혀 변경하지 않고도 StandardPricingWeekendDiscountPricing으로 쉽게 교체할 수 있습니다. 이것이 바로 의존성 주입과 결합된 전략 패턴의 강력함입니다!

직접 해보기

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

class Program
{
    public static void Main(string[] args)
    {
        // 가격 책정 전략 유형 읽기
        string strategyType = Console.ReadLine();
        
        // TODO: 입력에 따라 적절한 가격 책정 전략 생성
        // "standard" -> StandardPricing
        // "weekend" -> WeekendDiscountPricing
        IPricingStrategy strategy = null; // TODO: strategyType에 따라 초기화
        
        // TODO: 가격 책정 전략을 사용하여 RentalService 생성
        
        // 차량 수 읽기
        int vehicleCount = Convert.ToInt32(Console.ReadLine());
        
        // TODO: 각 차량을 읽고 서비스에 추가
        // 각 차량에 대해 다음을 읽음:
        // - type (car, motorcycle, truck)
        // - license plate
        // - brand
        // - daily rate
        // - 유형별 특정 값 (seats, engineCC, 또는 cargo capacity)
        
        // 작업 수 읽기
        int operationCount = Convert.ToInt32(Console.ReadLine());
        
        // TODO: 각 작업 처리
        // 작업: rent, return, available
        // 
        // "rent"의 경우:
        //   customerName, licensePlate, days 읽기
        //   출력: "Rented: {Brand} ({LicensePlate}) to {CustomerName} for {Days} days - Total: {TotalPrice}"
        //   또는: "Rental failed: {licensePlate}"
        //
        // "return"의 경우:
        //   licensePlate 읽기
        //   출력: "Returned: {licensePlate}" 또는 "Return failed: {licensePlate}"
        //
        // "available"의 경우:
        //   각 가용 차량을 다음과 같이 출력:
        //   "{Type}: {Brand} ({LicensePlate}) - {DailyRate}/day"
    }
}

객체 지향 프로그래밍의 모든 레슨