In diesem Artikel gehen wir eine Low-Level-Design-Implementierung (LLD) eines Parkplatzsystems in Go durch. Wir werden verschiedene Aspekte des Systems untersuchen und sehen, wie jede Komponente mit den anderen interagiert. Diese Implementierung konzentriert sich auf Klarheit und praktischen Nutzen, sodass Sie sie problemlos erweitern können, wenn Sie Funktionen wie mehr Fahrzeugtypen, mehrere Zahlungsoptionen oder Platzreservierungen hinzufügen möchten.
Das System übernimmt Aufgaben wie die Verwaltung von Parkebenen und -plätzen, das Ein- und Ausparken von Fahrzeugen sowie die Zahlungsabwicklung. Wir stellen außerdem sicher, dass es für den gleichzeitigen Zugriff threadsicher ist, damit es bei einer Erweiterung auf ein größeres System nicht unter Druck zusammenbricht.
Unser Design umfasst sechs Hauptkomponenten:
Unser ParkingLot verwendet das Singleton-Muster. Das bedeutet, dass es nur eine Instanz des Parkplatzes gibt, die einmal erstellt und in der gesamten Anwendung wiederverwendet wird. Hier ist der Code, um das zum Laufen zu bringen:
var ( parkingLotInstance *ParkingLot once sync.Once ) type ParkingLot struct { Name string floors []*ParkingFloor } func GetParkingLotInstance() *ParkingLot { once.Do(func() { parkingLotInstance = &ParkingLot{} }) return parkingLotInstance }
Mit sync.Once stellen wir sicher, dass nur eine Instanz erstellt wird, auch wenn mehrere Goroutinen darauf zugreifen.
Der Parkplatz verfügt über mehrere Etagen mit jeweils ausgewiesenen Parkplätzen für verschiedene Fahrzeugtypen (z. B. Autos, Transporter, Lastwagen und Motorräder). Um dem Parkplatz eine Etage hinzuzufügen, verwenden wir die AddFloor-Methode:
func (p *ParkingLot) AddFloor(floorID int) { p.floors = append(p.floors, NewParkingFloor(floorID)) }
Jede Etage wird mit der NewParkingFloor-Funktion erstellt, die Plätze nach Fahrzeugtyp organisiert.
Jeder ParkingSpot ist einem bestimmten Fahrzeugtyp zugeordnet (z. B. einem Auto oder einem Motorrad). Dadurch kann das System verwalten und einschränken, welche Fahrzeuge an welchen Stellen parken dürfen. Hier ist die ParkingSpot-Struktur und die ParkVehicle-Methode:
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 }
Wir verwenden eine Mutex-Sperre, um sicherzustellen, dass jeweils nur ein Fahrzeug an einem Parkplatz parken kann.
Jedes Fahrzeug erhält ein Ticket mit Einfahrtszeit, Ausfahrtzeit, Parkplatz und Gesamtgebühr. Dieses Ticket wird aktualisiert, wenn das Fahrzeug ausfährt, und die Gebühren werden auf der Grundlage der Parkzeit berechnet.
var ( parkingLotInstance *ParkingLot once sync.Once ) type ParkingLot struct { Name string floors []*ParkingFloor } func GetParkingLotInstance() *ParkingLot { once.Do(func() { parkingLotInstance = &ParkingLot{} }) return parkingLotInstance }
Die CalculateTotalCharge-Methode berechnet Parkgebühren basierend auf Fahrzeugtyp und -dauer.
Die PaymentSystem-Klasse verarbeitet die Zahlung und aktualisiert den Zahlungsstatus basierend darauf, ob der erforderliche Betrag bezahlt wurde:
func (p *ParkingLot) AddFloor(floorID int) { p.floors = append(p.floors, NewParkingFloor(floorID)) }
Die ProcessPayment-Funktion prüft den Betrag und aktualisiert den Zahlungsstatus auf „Abgeschlossen“ oder „Fehlgeschlagen“.
Unser System unterstützt verschiedene Fahrzeugtypen (Autos, Lieferwagen, Lastwagen und Motorräder). Für jeden Typ gelten unterschiedliche Stundensätze. Dies wird durch die Einrichtung eines VehicleType und VehicleInterface in einem separaten Fahrzeugpaket erreicht:
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 }
Wir können neue Fahrzeuge erstellen, indem wir NewCar, NewVan, NewTruck usw. aufrufen, die jeweils VehicleInterface implementieren.
Mal sehen, wie die Teile in einem Fluss zusammenpassen:
Dieses Parkplatzsystem ist ein vereinfachter Ausgangspunkt für den Aufbau komplexerer Systeme. Wir haben die Grundlagen der Boden- und Stellplatzverwaltung, des Ein- und Ausparkens von Fahrzeugen sowie einen grundlegenden Zahlungsvorgang behandelt.
Informationen zur vollständigen Code-Implementierung finden Sie im folgenden Repository:
Willkommen im Repository Low-Level-Systemdesign in Go! Dieses Repository enthält verschiedene Low-Level-Systemdesignprobleme und ihre in Go implementierten Lösungen. Das primäre Ziel besteht darin, den Entwurf und die Architektur von Systemen anhand praktischer Beispiele zu demonstrieren.
Systemdesign auf niedriger Ebene beinhaltet das Verständnis der Kernkonzepte der Systemarchitektur und das Entwerfen skalierbarer, wartbarer und effizienter Systeme. In diesem Repository wird versucht, Lösungen für verschiedene Probleme und Szenarien mit Go abzudecken.
Das erste Projekt in diesem Repository ist ein Parkplatzsystem. Dieses System simuliert einen Parkplatz, auf dem Fahrzeuge ein- und ausgeparkt werden können. Es zeigt:
Das obige ist der detaillierte Inhalt vonSystemdesign: Aufbau eines Parkplatzsystems in Go. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!