車両レンタルサービス
CoddyのC#ジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 70/70。
チャレンジ
簡単継承、インターフェース、そして Strategy パターンを組み合わせた車両レンタルサービスを構築しましょう!柔軟な料金戦略を使用してさまざまな種類の車両をレンタルできるシステムを作成し、OOP がどのように保守可能で拡張性の高いビジネスロジックを可能にするかを実証します。
コードは以下の 6 つのファイルに整理します:
Vehicle.cs:Rental.Models名前空間に車両の階層構造を作成します。ベースとなるVehicleクラスは、読み取り専用のLicensePlateとBrandプロパティ、DailyRate(decimal)、およびMarkAsRented()とMarkAsReturned()メソッドを通じて制御されるプライベートセッターを持つIsAvailableプロパティを持つ必要があります。次に、3 つの派生クラスを作成します:Seatsプロパティを持つCar、EngineCCプロパティを持つMotorcycle、およびCargoCapacity(decimal) プロパティを持つTruckです。各派生クラスはベースクラスのコンストラクタを呼び出し、固有のプロパティを設定する必要があります。IPricingStrategy.cs:Rental.Pricing名前空間に、decimal を返す単一のメソッドCalculatePrice(Vehicle vehicle, int days)を持つIPricingStrategyインターフェースを定義します。PricingStrategies.cs:Rental.Pricing名前空間に 2 つの料金戦略を実装します。StandardPricingは、単純に車両の 1 日あたりの料金に日数を掛けます。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)、ナンバープレート、ブランド、1 日あたりの料金、およびタイプ固有の値(座席数、排気量、または積載量) - 実行する操作の数
- 各操作について:アクションとそれに続く関連データ
操作の形式:
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 に簡単に交換できます。これが、依存性の注入と組み合わせた Strategy パターンの力です!
自分で試してみよう
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"
}
}