+ 2

How to separate payment strategy | Parking lot design

Hi I had a class which manages a parking lot. That class is called say for example, parking lot manager. I have a payment strategy stored in parking lot manager . This strategy is nothing but hourly payment or daily payment. Reason of storing it on manager is to avoid storing it into each and every vehicle object. But challenge is as below: For example, V1 came at 5 PM and that time, strategy was hourly basis. When it left at 11 PM, current strategy is no more hourly basis. How to handle this? I do not want to store strategy on vehicle object as it is duplicate on all the vehicle object and other issue is that it has nothing to do with vehicle. Vehicle is not something which decides the payment strategy , but it is parking lot which decides the strategy of payment. Please suggest.

7th Apr 2025, 1:50 PM
Ketan Lalcheta
Ketan Lalcheta - avatar
17 Answers
+ 2
I might not understand the question well but I would recommend reading up on design patterns (or review if you already have). The resource almost everyone uses (and builds up on) is called "gang of four" To me this sounds like a job great for an observer design pattern. - When a car parks in the lot, the observer notifies the manager and the manager sets up stats for that specific vehicle (time and date of arrival and a unique id, for example) -- When a car leaves, the observer notifies the manager and the manager handles that accordingly (delete the statistics, check if payment due is paid in full, then mark the parking spot as empty) - then, every minute, check the time of arrival for every car: if it's been an hour, charge them. An observer is a bit lengthy to explain for your question, but its only job should be to "keep a lookout" for vehicles; the manager handles the payments Since the parking lot decides the payments, i believe it's fine to keep payment strategies within a parking lot class
7th Apr 2025, 4:53 PM
「HAPPY TO HELP」
「HAPPY TO HELP」 - avatar
+ 2
strategy pattern feels like overkill. you end up having to clean up classes that you don't really need. feels like setting up a Rube Goldberg machine to do a simple task. https://en.wikipedia.org/wiki/Rube_Goldberg_machine
8th Apr 2025, 3:36 PM
Bob_Li
Bob_Li - avatar
+ 2
it's ok and i apologize for being late; i assume others have helped you already
9th Apr 2025, 1:25 AM
「HAPPY TO HELP」
「HAPPY TO HELP」 - avatar
+ 1
My bad . Let me try to rephrase the question. Abstract class to calculate parking cost. It has details about the time at which it was Parked initially. So, we can calculate the cost based on total time. Now, cost is calculated as two strategy as below : 1. Hourly based cost If this is adopted, for 3 hours cost is 3*1 = 3$ where as for 4 hours, cost is 4*1 2. Day based cost If this strategy was adopted , 3 or 4 hour cost of parking vehicle is same. Now coming to my query, where to store this strategy (either to compute based on day or based on hour) If I store it on each vehicle , it duplicates on each vehicle object. If I store it on parking manager object, it may not remain consistent at vehicle entry and vehicle exit.
7th Apr 2025, 5:12 PM
Ketan Lalcheta
Ketan Lalcheta - avatar
+ 1
each vehicle should perhaps store its entry time. then you would just need a parking lot method that computes the parking fee based on the entry time data and the time it exits the parking lot. I'm a bit unclear on when you should adopt the hourly or daily rate (the pricing algorithm). Is it the vehicle's decision or based on the time it's parked(the parking lot's decision)? also, in your example, hourly rate computes the same for 3 and 4 hours (3*1, 4*1) or $1 per hour. what's the cut-off time? 3 hours? rate differential? does it get costlier or cheaper? so many questions... perhaps it's easier if you gave a sample code... also, does everything have to be OOP? OOP is just an abstraction that's useful if you have to encapsulate a lot of data into multiple instances. Here you are just concerned about the entry and exit times, or the parking duration. OOP feels like overcomplication. a single function could probably compute the fee in a more efficient manner...
8th Apr 2025, 1:23 AM
Bob_Li
Bob_Li - avatar
+ 1
i notice several inconsistencies in your code. your hourly rate seems too high. you're basically charging $5/second. your daily rate is too low. you're charging 5$/day... is it supposed to be that way? the way it's set up, your Vehicle class is the only one you have. you don't have a Parkinglot class, so all computations are done as Vehicle methods. if it doesn't feel right, maybe you can refactor it as an independent function.
8th Apr 2025, 11:46 AM
Bob_Li
Bob_Li - avatar
+ 1
perhaps you can use enum as flags instead of virtual class inheritance. i made a few changes to your code: I also detatched the fee calculation to an external function. also, if there is no real reason for private properties, using a struct with all public properties would simplify the code even more, by eliminating the getters. I did that in the second code with struct instead of class https://sololearn.com/compiler-playground/c53Q01EbKCGX/?ref=app https://sololearn.com/compiler-playground/c6vx4wzvwNv9/?ref=app
8th Apr 2025, 2:31 PM
Bob_Li
Bob_Li - avatar
+ 1
If you MUST use the strategy pattern, putting the fee calculation on the vehicle feels wrong. The vehicle should not be responsible for fee calculation. But in your sample code, you don't have a parking lot manager. maybe that's what's missing. you passed the responsibility of calculating the fee to a method in the Vehicle.
8th Apr 2025, 4:15 PM
Bob_Li
Bob_Li - avatar
+ 1
most parking lots have a per hour fee, with the time rounded up. some have higher than normal rates on evenings or holidays. some offer discounts if you shop at affiliate stores. some have a lower daily charge if you buy a monthly plan. so you have potentially lots of payment strategies. That's why using an enum switch flag is the simpler option. the car can probably be reduced to a struct with id or plate number, parking spot, park start and park end times, payment strategy and possibly a discount flag. it's basically just a data container. what's important is that your fee calculator have to be able to compute the parking duration and process the struct data as well as to switch the payment algorithms accordingly. concentrate on processing the data to compute the fee. Don't get obsessed on design algorithms and creating an accurate OOP model. they're abstracted away when your code is compiled.
8th Apr 2025, 10:04 PM
Bob_Li
Bob_Li - avatar
+ 1
Assume theres x parking spots . = open d = daily rate h = hourly rate ParkingManager - char parkingSpotState[x] - string timeIn[x] - payParking(spot)
9th Apr 2025, 12:52 AM
Raul Ramirez
Raul Ramirez - avatar
+ 1
Raul Ramirez i see it as // data Car { id, rate: hourly | daily | ... // payment options time in time out } // function // no need to observe, just process data when car leaves ParkingCalculator( car ) { hourly ? calculate parking time calculate fee daily ? calculate parking time calculate fee ... ? ... process payment... }
9th Apr 2025, 1:06 AM
Bob_Li
Bob_Li - avatar
+ 1
Ketan Lalcheta from: https://refactoring.guru/design-patterns/strategy "A lot of modern programming languages have functional type support that lets you implement different versions of an algorithm inside a set of anonymous functions. Then you could use these functions exactly as you’d have used the strategy objects, but without bloating your code with extra classes and interfaces." which I interpret as: while you can use OOP style strategy pattern, you don't have to if you have alternatives. Remember you have extra overhead of constructors and destructors when using OOP extensively.
9th Apr 2025, 5:28 AM
Bob_Li
Bob_Li - avatar
0
Here is a very basic code: I was concerned about storing strategy pointer for cost calculation . Should it be on vehicle object ? https://sololearn.com/compiler-playground/cOBcKXuPYHZv/?ref=app
8th Apr 2025, 11:21 AM
Ketan Lalcheta
Ketan Lalcheta - avatar
0
Hi Bob_Li you can ignore rate at which cost is calculated. It is not that much important as this is dummy code. I wanted to give a feel of strategy pattern which decides how cost is calculated. My main concern is whether to have it on each vehicle object making part of class vehicle or not.
8th Apr 2025, 3:30 PM
Ketan Lalcheta
Ketan Lalcheta - avatar
0
Plz understand that this is not the production code. My base query was about where to put the strategy code , on controller of parking lot manager or on vehicle class. You requested sample code and now with sample code, you are suggesting not to use strategy pattern. Please focus on original question
8th Apr 2025, 3:40 PM
Ketan Lalcheta
Ketan Lalcheta - avatar
0
I agree. If I don't have vehicle holding the strategy, it is not good choice. If I go with strategy hold on parking lot manager, it is issue as I mentioned in query. That issue is the mapping of strategy at exit or entry time. Say for example, strategy was hourly basis at 5 PM and then vehicle parked. It is no guarantee that it will still be a hourly base strategy when vehicle left the space. How to handle this
8th Apr 2025, 5:21 PM
Ketan Lalcheta
Ketan Lalcheta - avatar
0
Sounds great bishopsky
24th Apr 2025, 3:33 AM
Ketan Lalcheta
Ketan Lalcheta - avatar