Usługa wynajmu pojazdów
Część sekcji Programowanie obiektowe ścieżki C# w Coddy. Lekcja 70 z 70.
Wyzwanie
ŁatwyZbudujmy system wypożyczania pojazdów, który łączy dziedziczenie, interfejsy i wzorzec Strategia! Stworzysz system, w którym można wypożyczać różne typy pojazdów, korzystając z elastycznych strategii cenowych — pokażemy, jak OOP umożliwia tworzenie łatwej w utrzymaniu i rozszerzaniu logiki biznesowej.
Rozmieścisz kod w sześciu plikach:
Vehicle.cs: Utwórz hierarchię pojazdów w przestrzeni nazwRental.Models. Bazowa klasaVehiclepowinna mieć tylko do odczytu właściwościLicensePlateiBrand, właściwośćDailyRate(decimal) oraz właściwośćIsAvailablez prywatnym setterem, której stan zmienia się za pomocą metodMarkAsRented()iMarkAsReturned(). Następnie utwórz trzy klasy pochodne:Carz właściwościąSeats,Motorcyclez właściwościąEngineCCorazTruckz właściwościąCargoCapacity(decimal). Każda klasa pochodna powinna wywoływać konstruktor klasy bazowej i ustawiać swoją unikatową właściwość.IPricingStrategy.cs: Zdefiniuj interfejsIPricingStrategyw przestrzeni nazwRental.Pricingz jedną metodąCalculatePrice(Vehicle vehicle, int days), która zwraca wartość typu decimal.PricingStrategies.cs: Zaimplementuj dwie strategie cenowe w przestrzeni nazwRental.Pricing.StandardPricingpo prostu mnoży dzienną stawkę za pojazd przez liczbę dni.WeekendDiscountPricingudziela 10% zniżki (mnoży przez 0.9), jeśli wypożyczenie trwa 2 dni lub dłużej; w przeciwnym razie stosuje standardowe obliczenie.RentalRecord.cs: Utwórz klasęRentalw przestrzeni nazwRental.Models, która będzie przechowywać informacje o wypożyczeniach. Powinna mieć tylko do odczytu właściwościCustomerName(string),Vehicle(Vehicle),Days(int) iTotalPrice(decimal), ustawiane za pomocą konstruktora.RentalService.cs: Utwórz klasęRentalServicew przestrzeni nazwRental.Services, która zarządza flotą i obsługuje wypożyczenia. OtrzymujeIPricingStrategyza pośrednictwem konstruktora (wstrzykiwanie zależności). Zaimplementuj:AddVehicle(Vehicle vehicle)— dodaje pojazd do flotyRentVehicle(string customerName, string licensePlate, int days)— zwraca obiektRental, jeśli pojazd istnieje i jest dostępny; w przeciwnym razie zwracanull. Pamiętaj, aby oznaczyć pojazd jako wypożyczony i obliczyć cenę przy użyciu wstrzykniętej strategii.ReturnVehicle(string licensePlate)— oznacza pojazd jako dostępny i zwracatrue, jeśli operacja się powiedzieGetAvailableVehicles()— zwraca listę wszystkich dostępnych pojazdów
Program.cs: Połącz wszystkie elementy, tworząc pojazdy, konfigurując usługę ze strategią cenową i obsługując operacje wypożyczania na podstawie danych wejściowych.
Otrzymasz następujące dane wejściowe:
- Strategię cenową do zastosowania (
standardlubweekend) - Liczbę pojazdów do dodania
- Dla każdego pojazdu: typ (
car,motorcyclelubtruck), numer rejestracyjny, markę, stawkę dzienną i wartość charakterystyczną dla danego typu (liczbę miejsc, engineCC lub ładowność) - Liczbę operacji do wykonania
- Dla każdej operacji: działanie, a następnie odpowiednie dane
Formaty operacji:
rent
{customerName}
{licensePlate}
{days}
return
{licensePlate}
availableFormaty wyników:
- Udane wypożyczenie:
Rented: {Brand} ({LicensePlate}) to {CustomerName} for {Days} days - Total: {TotalPrice} - Nieudane wypożyczenie:
Rental failed: {licensePlate} - Udany zwrot:
Returned: {licensePlate} - Nieudany zwrot:
Return failed: {licensePlate} - Dostępne pojazdy: Wypisz każdy dostępny pojazd w formacie
{Type}: {Brand} ({LicensePlate}) - {DailyRate}/day, gdzie Type to "Car", "Motorcycle" lub "Truck"
Na przykład dla następujących danych wejściowych:
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-123Wynik powinien być następujący:
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.0
Rental failed: ABC-123
Motorcycle: Honda (XYZ-789) - 30/day
Truck: Ford (TRK-001) - 80/day
Returned: ABC-123Zwróć uwagę, jak strategia cenowa jest wstrzykiwana do usługi — możesz łatwo zamienić StandardPricing na WeekendDiscountPricing, nie zmieniając ani trochę kodu RentalService. Na tym polega siła wzorca Strategia w połączeniu z wstrzykiwaniem zależności!
Spróbuj swoich sił
using System;
using System.Collections.Generic;
using Rental.Models;
using Rental.Pricing;
using Rental.Services;
class Program
{
public static void Main(string[] args)
{
// Wczytaj typ strategii ustalania cen
string strategyType = Console.ReadLine();
// TODO: Utwórz odpowiednią strategię ustalania cen na podstawie danych wejściowych
// "standard" -> StandardPricing
// "weekend" -> WeekendDiscountPricing
IPricingStrategy strategy = null; // TODO: Zainicjalizuj na podstawie strategyType
// TODO: Utwórz RentalService ze strategią ustalania cen
// Wczytaj liczbę pojazdów
int vehicleCount = Convert.ToInt32(Console.ReadLine());
// TODO: Wczytaj każdy pojazd i dodaj go do usługi
// Dla każdego pojazdu wczytaj:
// - typ (samochód, motocykl, ciężarówka)
// - numer rejestracyjny
// - marka
// - stawka dzienna
// - wartość zależna od typu pojazdu (liczba miejsc, engineCC lub ładowność)
// Wczytaj liczbę operacji
int operationCount = Convert.ToInt32(Console.ReadLine());
// TODO: Przetwórz każdą operację
// Operacje: rent, return, available
//
// Dla "rent":
// Wczytaj customerName, licensePlate, days
// Wypisz: "Rented: {Brand} ({LicensePlate}) to {CustomerName} for {Days} days - Total: {TotalPrice}"
// Lub: "Rental failed: {licensePlate}"
//
// Dla "return":
// Wczytaj licensePlate
// Wypisz: "Returned: {licensePlate}" lub "Return failed: {licensePlate}"
//
// Dla "available":
// Wyświetl każdy dostępny pojazd w formacie:
// "{Type}: {Brand} ({LicensePlate}) - {DailyRate}/day"
}
}
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrznePrzestrzenie nazw i dyrektywyWprowadzenie do klas i obiektówSłowo kluczowe „this”Metody i parametryPola a właściwościKonstruktoryInicjalizatory obiektówPodsumowanie — prosty kalkulator4Dziedziczenie
Podstawowa składnia dziedziczenia (:)Słowo kluczowe 'base'Słowa kluczowe virtual i overrideKlasy sealedBazowa klasa 'object'Powtórzenie – hierarchia pracowników7Zaawansowane funkcje
Przeciążanie operatorówIndeksery (this[])Nadpisywanie ToString()Metody rozszerzającePodsumowanie – własna lista2Właściwości i składowe statyczne
Właściwości automatyczneWłaściwości tylko do odczytu i zapisuPola i metody statyczneKlasy statyczneSkładowe z ciałem wyrażeniowym5Polimorfizm i interfejsy
Polimorfizm czasu kompilacji a czasu wykonaniaInterfejs a klasa abstrakcyjnaWiele interfejsówJawne implementowanie interfejsówRzutowanie w górę i w dółPowtórka — kalkulator kształtów8Zaawansowane koncepcje OOP
Kompozycja zamiast dziedziczeniaTypy generyczne (klasy i metody)Delegaty i zdarzeniaAtrybuty i refleksjaIDisposable i instrukcja usingPodstawy wstrzykiwania zależności11Wzorce projektowe, część 2
Wzorzec poleceniaWzorzec adapteraWzorzec dekoratoraWzorzec metody szablonowejWzorzec stanuWzorzec kompozytu3Architektura klas
Dane instancji a dane statyczneSłowa kluczowe 'readonly' i 'const'Pola zapasowePowtórzenie — menedżer kont bankowych6Hermetyzacja
Modyfikatory dostępuWłaściwości w hermetyzacjiImplementacja ukrywania danychWzorce niezmiennościPowtórka — dane studentów9Argumenty zmiennej liczby
Słowo kluczowe „params”Parametry opcjonalneArgumenty nazwanePrzeciążanie metodPoćwicz samodzielnie: Kompilator C# online