在本文中,我們將介紹 Go 中停車場系統的低階設計 (LLD) 實作。我們將探索系統的不同方面,並了解每個組件如何與其餘組件互動。此實現側重於清晰度和現實世界的實用性,因此如果您想添加更多車輛類型、多種付款選項或現貨預訂等功能,您可以輕鬆擴展它。
系統處理諸如管理停車樓層和停車位、停放車輛和處理付款等任務。我們還將確保它對於並發存取是線程安全的,因此如果我們需要將其擴展到更大的系統,它不會在壓力下崩潰。
我們的設計包括六個主要組成部分:
我們的停車場使用單例模式。這意味著停車場只有一個實例,該實例創建一次並在整個應用程式中重複使用。這是使其正常工作的程式碼:
var ( parkingLotInstance *ParkingLot once sync.Once ) type ParkingLot struct { Name string floors []*ParkingFloor } func GetParkingLotInstance() *ParkingLot { once.Do(func() { parkingLotInstance = &ParkingLot{} }) return parkingLotInstance }
使用sync.Once,我們確保只建立一個實例,即使被多個 goroutine 存取也是如此。
停車場有多層,每層都有不同車輛類型(例如汽車、貨車、卡車和摩托車)的指定停車位。若要為停車場新增樓層,我們使用 AddFloor 方法:
func (p *ParkingLot) AddFloor(floorID int) { p.floors = append(p.floors, NewParkingFloor(floorID)) }
每個樓層都是使用 NewParkingFloor 函數創建的,該函數按車輛類型組織停車位。
每個 ParkingSpot 都與特定的車輛類型(例如汽車或摩托車)相關聯。這使得系統能夠管理和限制每個停車位可以停放的車輛。這是 ParkingSpot 結構和 ParkVehicle 方法:
type ParkingSpot struct { SpotID int VehicleType vehicles.VehicleType CurrentVehicle *vehicles.VehicleInterface lock sync.Mutex } func (p *ParkingSpot) ParkVehicle(vehicle vehicles.VehicleInterface) error { p.lock.Lock() defer p.lock.Unlock() if vehicle.GetVehicleType() != p.VehicleType { return fmt.Errorf("vehicle type mismatch: expected %s, got %s", p.VehicleType, vehicle.GetVehicleType()) } if p.CurrentVehicle != nil { return fmt.Errorf("parking spot already occupied") } p.CurrentVehicle = &vehicle return nil }
我們使用互斥鎖來確保同一時間只能停放一輛車。
每輛車都會收到一張票,上面有進入時間、退出時間、停車位和總費用。此票會在車輛退出時更新,並根據停車時間計算費用。
var ( parkingLotInstance *ParkingLot once sync.Once ) type ParkingLot struct { Name string floors []*ParkingFloor } func GetParkingLotInstance() *ParkingLot { once.Do(func() { parkingLotInstance = &ParkingLot{} }) return parkingLotInstance }
CalculateTotalCharge 方法根據車輛類型和持續時間計算停車費。
PaymentSystem 類別處理付款,依照是否支付所需金額更新付款狀態:
func (p *ParkingLot) AddFloor(floorID int) { p.floors = append(p.floors, NewParkingFloor(floorID)) }
ProcessPayment 函數檢查金額並將付款狀態更新為「已完成」或「失敗」。
我們的系統支援不同類型的車輛(汽車、貨車、卡車和摩托車)。每種類型的每小時費用不同。這是透過在單獨的車輛包中設定 VehicleType 和 VehicleInterface 來實現的:
type ParkingSpot struct { SpotID int VehicleType vehicles.VehicleType CurrentVehicle *vehicles.VehicleInterface lock sync.Mutex } func (p *ParkingSpot) ParkVehicle(vehicle vehicles.VehicleInterface) error { p.lock.Lock() defer p.lock.Unlock() if vehicle.GetVehicleType() != p.VehicleType { return fmt.Errorf("vehicle type mismatch: expected %s, got %s", p.VehicleType, vehicle.GetVehicleType()) } if p.CurrentVehicle != nil { return fmt.Errorf("parking spot already occupied") } p.CurrentVehicle = &vehicle return nil }
我們可以透過呼叫NewCar、NewVan、NewTruck等來創建新的車輛,它們都實現了VehicleInterface。
讓我們看看各個部分如何在流程中組合在一起:
這個停車場系統是建造更複雜系統的簡化起點。我們介紹了樓層和停車位管理、車輛停車和出庫以及基本付款流程的基礎知識。
有關完整程式碼實現,請檢查以下儲存庫:
歡迎來到Go 中的低階系統設計 儲存庫!此儲存庫包含各種低階系統設計問題及其在 Go 中實現的解決方案。主要目的是透過實際範例展示系統的設計和架構。
底層系統設計涉及理解系統架構的核心概念以及設計可擴展、可維護和高效的系統。該儲存庫將嘗試涵蓋使用 Go 的各種問題和場景的解決方案。
此儲存庫中的第一個項目是停車場系統。該系統模擬一個可以停放車輛和出庫車輛的停車場。它示範了:
以上是系統設計:用Go建造停車場系統的詳細內容。更多資訊請關注PHP中文網其他相關文章!