Menu
Coddy logo textTech

車両レンタルサービス

CoddyのC#ジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 70/70。

challenge icon

チャレンジ

簡単

継承、インターフェース、そして Strategy パターンを組み合わせた車両レンタルサービスを構築しましょう!柔軟な料金戦略を使用してさまざまな種類の車両をレンタルできるシステムを作成し、OOP がどのように保守可能で拡張性の高いビジネスロジックを可能にするかを実証します。

コードは以下の 6 つのファイルに整理します:

  • Vehicle.cs: Rental.Models 名前空間に車両の階層構造を作成します。ベースとなる Vehicle クラスは、読み取り専用の LicensePlateBrand プロパティ、DailyRate (decimal)、および MarkAsRented()MarkAsReturned() メソッドを通じて制御されるプライベートセッターを持つ IsAvailable プロパティを持つ必要があります。次に、3 つの派生クラスを作成します:Seats プロパティを持つ CarEngineCC プロパティを持つ 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 のコードを一切変更することなく、StandardPricingWeekendDiscountPricing に簡単に交換できます。これが、依存性の注入と組み合わせた 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"
    }
}

オブジェクト指向プログラミングのすべてのレッスン