차량 대여 서비스
Coddy C# 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 70개 중 70번째.
챌린지
쉬움상속, 인터페이스, 그리고 전략(Strategy) 패턴을 결합한 차량 대여 서비스를 구축해 봅시다! 유연한 가격 책정 전략을 사용하여 다양한 차량 유형을 대여할 수 있는 시스템을 만들게 됩니다. 이를 통해 객체 지향 프로그래밍(OOP)이 어떻게 유지보수가 쉽고 확장 가능한 비즈니스 로직을 가능하게 하는지 실습해 볼 것입니다.
코드는 다음 여섯 개의 파일로 구성됩니다:
Vehicle.cs:Rental.Models네임스페이스에 차량 계층 구조를 만듭니다. 기본Vehicle클래스는 읽기 전용인LicensePlate와Brand속성,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 코드를 전혀 변경하지 않고도 StandardPricing을 WeekendDiscountPricing으로 쉽게 교체할 수 있습니다. 이것이 바로 의존성 주입과 결합된 전략 패턴의 강력함입니다!
직접 해보기
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"
}
}