車両レンタルサービス
CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 87/87。
この最後のチャレンジでは、このコース全体で習得したすべてのOOPの概念を統合した車両レンタルサービスシステムを構築します。
システムは、さまざまな種類の車両フリートをモデル化する必要があります。ナンバープレート、ブランド、1日あたりのレンタル料金などの共通プロパティを持つ、ベースとなる Vehicle クラスを検討してください。Car、Motorcycle、および Truck などのサブクラスは、座席数、エンジンサイズ、または積載量などの特定の属性を使用して、これを拡張できます。
インターフェースはレンタルの動作を定義できます。Rentableインターフェースは、rent()、returnVehicle()、およびcalculateCost(int days)のようなメソッドを宣言するかもしれません。異なる車両タイプは価格戦略を異なる方法で実装できるため、これはポリモーフィズムの完璧なユースケースになります。
RentalAgencyクラスがコンポジションを使用してフリートを管理する方法について考えてみましょう。
VehicleNotAvailableException のようなカスタム例外を使用することで、エッジケースを処理できます。
車両を作成するためにFactoryパターンを適用したり、車両のカテゴリやレンタル状況にenumを使用したりするかもしれません。
このチャレンジは、完全で適切に構造化されたOOPシステムを設計する能力をテストします。頑張ってください!
チャレンジ
簡単これまで学んだOOPのすべてを統合した、完全な車両レンタルサービスを構築しましょう!さまざまな種類の車両フリートを管理し、適切なバリデーションを伴うレンタル処理を行い、ファクトリーパターンのように車両を作成するシステムを作成します。
コードは以下の7つのファイルに分けて構成します:
RentalStatus.java: 車両のレンタル状況を表す列挙型(enum)を作成します。AVAILABLE、RENTED、MAINTENANCEの値を含めてください。プライベートフィールドdescription(String)、コンストラクタ、およびゲッターを追加します。Availableの記述は "ready to rent"、rentedは "currently in use"、maintenanceは "under service" としてください。VehicleNotAvailableException.java:Exceptionを継承したカスタム例外を作成します。コンストラクタはライセンスプレートを受け取り、Vehicle not available: [licensePlate]という形式のメッセージを作成する必要があります。Rentable.java: レンタル操作を定義するインターフェースを作成します。booleanを返すrent()メソッド、booleanを返すreturnVehicle()メソッド、およびdoubleを返すcalculateCost(int days)メソッドを宣言してください。Vehicle.java: すべての車両の基底となる抽象クラスを作成します。licensePlate(String)、brand(String)、dailyRate(double)、およびstatus(RentalStatus、初期値は AVAILABLE) のプライベートフィールドを含めます。コンストラクタは licensePlate、brand、dailyRate を引数に取ります。適切なゲッターと status のセッターを含めてください。Stringを返す抽象メソッドgetVehicleType()を宣言します。"[licensePlate] [brand] ([vehicleType]) - $[dailyRate]/day - [status description]"を返すgetDetails()メソッドを実装してください(dailyRate は小数点以下2桁でフォーマットします)。Car.java: Vehicle を継承し、Rentable を実装するクラスを作成します。プライベートフィールドseats(int) を追加します。コンストラクタは licensePlate, brand, dailyRate, seats を引数に取ります。getVehicleType()を実装して"Car"を返すようにします。rent()では、status が AVAILABLE の場合に RENTED に設定して true を返し、それ以外の場合は false を返します。returnVehicle()では、status が RENTED の場合に AVAILABLE に設定して true を返し、それ以外の場合は false を返します。calculateCost(int days)では、dailyRate に days を掛けた値を返します。Motorcycle.java: Vehicle を継承し、Rentable を実装するクラスを作成します。プライベートフィールドengineCC(int) を追加します。コンストラクタは licensePlate, brand, dailyRate, engineCC を引数に取ります。getVehicleType()を実装して"Motorcycle"を返すようにします。Rentable インターフェースのメソッドは Car と同様に実装しますが、calculateCost()では10%の割引を適用(0.9を掛ける)してください。RentalAgency.java: ArrayList を使用して車両フリートを管理するクラスを作成します。以下のメソッドを含めてください:addVehicle(Vehicle vehicle)- フリートに車両を追加しますfindVehicle(String licensePlate)- 該当する Vehicle または null を返しますrentVehicle(String licensePlate, int days)- 車両を検索し、レンタルを試み(Rentable にキャスト)、レンタル費用を返します。車両が見つからない場合、または rent() が false を返した場合はVehicleNotAvailableExceptionをスローしますreturnVehicle(String licensePlate)- 車両を検索して返却処理を行い、成功した場合は true を返しますgetAvailableVehicles()- ステータスが AVAILABLE の車両の ArrayList を返します
Main.java: レンタルサービスを構築しましょう!カンマ区切りのコマンド文字列を受け取ります:ADD_CAR:licensePlate:brand:dailyRate:seatsADD_MOTORCYCLE:licensePlate:brand:dailyRate:engineCCRENT:licensePlate:daysRETURN:licensePlateAVAILABLE
各コマンドを処理し、以下を出力してください:
- ADD_CAR/ADD_MOTORCYCLE:
Added: [brand] ([vehicleType]) - RENT:
Rented [licensePlate] for [days] days - Total: $[cost](cost は小数点2桁まで)、またはError: [exception message] - RETURN:
Returned: [licensePlate]またはReturn failed: [licensePlate] - AVAILABLE:
Available vehicles:と出力し、その後に各利用可能な車両の詳細を個別の行に出力します
すべてのコマンドの後、
--- Fleet Summary ---と出力し、その後に各車両の詳細を出力します。
入力として、カンマ区切りのコマンド文字列を1つ受け取ります。
例えば、入力が ADD_CAR:ABC-123:Toyota:50.00:5,ADD_MOTORCYCLE:XYZ-789:Honda:40.00:600,RENT:ABC-123:3,RENT:ABC-123:2,AVAILABLE,RETURN:ABC-123 の場合、出力は以下のようになります:
Added: Toyota (Car)
Added: Honda (Motorcycle)
Rented ABC-123 for 3 days - Total: $150.00
Error: Vehicle not available: ABC-123
Available vehicles:
XYZ-789 Honda (Motorcycle) - $40.00/day - ready to rent
Returned: ABC-123
--- Fleet Summary ---
ABC-123 Toyota (Car) - $50.00/day - ready to rent
XYZ-789 Honda (Motorcycle) - $40.00/day - ready to rentこのチャレンジでは、継承(Vehicle 階層)、インターフェース(Rentable)、列挙型(RentalStatus)、カスタム例外、ポリモーフィズム(異なる車両タイプを統一的に扱う)、およびコンポジション(車両を管理する RentalAgency)を組み合わせて、完全なレンタルサービスシステムを構築します!
自分で試してみよう
import java.util.Scanner;
import java.util.ArrayList;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
// TODO: RentalAgency のインスタンスを作成する
// TODO: 入力をカンマで分割して個別のコマンドを取得する
// TODO: 各コマンドを処理する:
// ADD_CAR:licensePlate:brand:dailyRate:seats -> "Added: [brand] ([vehicleType])" を出力
// ADD_MOTORCYCLE:licensePlate:brand:dailyRate:engineCC -> "Added: [brand] ([vehicleType])" を出力
// RENT:licensePlate:days -> "Rented [licensePlate] for [days] days - Total: $[cost]" (小数点2桁) を出力
// または、例外がスローされた場合は "Error: [exception message]" を出力
// RETURN:licensePlate -> "Returned: [licensePlate]" または "Return failed: [licensePlate]" を出力
// AVAILABLE -> "Available vehicles:" に続いて、利用可能な各車両の詳細を出力
// TODO: すべてのコマンドの後、"--- Fleet Summary ---" を出力
// 続いて各車両の詳細を出力
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
4継承
継承の基本 (extends)super キーワードメソッドのオーバーライド (@Override)コンストラクタチェーンObject クラス単一継承と多段階継承なぜ多重継承ができないのかまとめ:従業員の階層構造