8.4 Design a parking lot using object-oriented principles.
LintCode上的原題,請參見我的另一篇博客Parking Lot 停車場問題。
這道題讓我們實現一個停車位的數據結構,由於題目沒給任何多余的信息,所以自由度很大,比如能停放什么種類的車,或是否是多層的等等。根據書中描述,這里我們做如下假設:
1. 停車場有多層,每層有多行停車位
2. 停車場可以停摩托車,小轎車和公交車
3. 停車場有摩托車位,緊湊型車位,和大型車位
4. 摩托車可以停在任何位置
5. 小轎車可以停在緊湊型車位和大型車位
6. 公交車只能停在同一行中連續的五個大型車位上,不能停在小位置上
有了這么多條件,我們就可以開始寫各種類了。首先可定要有個基本類Vehicle,然后摩托車,小轎車和公交車都可以派生出來,每個派生類和基類不同的是需要的空位數不同,還有就是車型不同,那么就要把基類的判斷是否能停在當前位置設為虛函數,在派生類中分別實現出來。我們還要用枚舉類VehicleSize來標識車型。然后就是要有停車場類ParkingLot,層類Level,停車位類ParkingSpot,它們之間錯綜復雜的關系請參見下列代碼:
enum class VehicleSize { Motorcycle, Compact, Large }; class Vehicle; class Level; class ParkingSpot { public: ParkingSpot(Level *lvl, int r, int n, VehicleSize s): _level(lvl), _row(r), _spotNumber(n), _spotSize(s) {} // ... bool isAvailable() { return _vehicle == nullptr; }; bool canFitVehicle(Vehicle *vehicle) {} // ... bool park(Vehicle *v) {} // ... int getRow() { return _row; } int getSpotNumber() { return _spotNumber; } void removeVehicle() {} // ... private: Vehicle *_vehicle = nullptr; VehicleSize _spotSize; int _row; int _spotNumber; Level *_level = nullptr; }; class Vehicle { public: Vehicle() {} int getSpotsNeeded() { return _spotsNeeded; } VehicleSize getSize() { return _size; } void parkInSpot(ParkingSpot s) { _parkingSpots.push_back(s); } void clearSpots() {} // ... virtual bool canFitInSpot(ParkingSpot spot) {} protected: vector<ParkingSpot> _parkingSpots; string _licensePlate; int _spotsNeeded; VehicleSize _size; }; class Bus: public Vehicle { public: Bus() { _spotsNeeded = 5; _size = VehicleSize::Large; } bool canFitInSpot(ParkingSpot spot) { } }; class Car: public Vehicle { public: Car() { _spotsNeeded = 1; _size = VehicleSize::Compact; } bool canFitInSpot(ParkingSpot spot) { } }; class Motorcycle: public Vehicle { public: Motorcycle() { _spotsNeeded = 1; _size = VehicleSize::Motorcycle; } bool canFitInSpot(ParkingSpot spot) { } }; class Level { public: Level() {} Level(int flr, int numberSpots): _floor(flr), _availableSpots(numberSpots) {} Level(const Level* lvl) { *this = *lvl; } int availableSpots() { return _availableSpots; } bool parkVehicle(Vehicle vehicle) {} // ... void spotFreed() { ++_availableSpots; } private: int _floor; vector<ParkingSpot> _spots; int _availableSpots = 0; static const int _SPOTS_PER_ROW = 10; bool parkStartingAtSpot(int num, Vehicle v) {} // ... int findAvailableSpots(Vehicle vehicle) {} // ... }; class ParkingLot { public: ParkingLot() {} // ... bool parkVehicle(Vehicle vehicle) {} // ... private: vector<Level> _levels; const int _NUM_LEVELS = 5; };