Cab Booking And Scheduling By Using Command Design Pattern And Scheduler

This article explains the cab booking & scheduling system by using Command Design Pattern and Scheduler.

Introduction

Command Pattern comes under behavioral pattern. It encapsulates all the information in an object for a particular action, that action to be performed at a later time. Cab Booking System can be developed using Command Design Pattern and using some scheduling algorithm along with.

Problem Statement

Develop an application for scheduling algorithms for such a cab service, provided, you have a list of future bookings, and a list of cabs in your fleet.

 
Example

Let's say, XYZ is a user and wants to travel by cars to the different locations on different scheduled dates and time. Below are the different scenarios:
 
Cabs available : Cab A, Cab B, Cab C
 
The user sees the available cabs -  Cab A, Cab B, Cab C and schedules booking as below.
  1. User XYZ books Cab A and schedules for 18/01/2018 15:30 PM
  2. User XYZ books CabB and schedules for 20/01/2018 12:30 PM
  3. User XYZ books CabC and schedules for 20/01/2018 16:30 PM 
Note

The user can cancel the scheduled cab before the arrival of the cab at the scheduled time. 
 
Solution

This problem statement can be solved by using "Command Design Pattern" which can use some scheduling algorithm because cab booking and cab cancellation and scheduling information will be encapsulated and these activities will be performed based on the user demand for a later time.
 
So, cab cancellation and cab scheduling algorithms will be written separately and encapsulated into one object for the execution based on the Command Design Pattern.
 
Diagrams

Dependency Diagram

Design Patterns & Practices

And another Dependency Diagram,

Design Patterns & Practices

Class Diagram,
 
Design Patterns & Practices
Code Explanation : Command Pattern

ICabService Interface 
  1. namespace CabScheduling.CabBooking  
  2. {  
  3.     public interface ICabService  
  4.     {  
  5.         void Execute();  
  6.     }  
  7. }  
BookCab Class,
  1. namespace CabScheduling.CabBooking  
  2. {  
  3.     public class BookCab : ICabService {  
  4.   
  5.         public readonly BookingRequest _bookingRequest;  
  6.         public BookCab(BookingRequest bookingRequest) {  
  7.             _bookingRequest = bookingRequest;  
  8.         }  
  9.   
  10.         public void Execute() {  
  11.             _bookingRequest.Book();  
  12.         }  
  13.     }  
  14. }  
CancelCab Class,
  1. namespace CabScheduling.CabBooking  
  2. {  
  3.     public class CancelCab : ICabService  
  4.     {  
  5.         public BookingRequest _bookingRequest;  
  6.   
  7.         public CancelCab(BookingRequest bookingRequest) {  
  8.             _bookingRequest = bookingRequest;  
  9.         }  
  10.   
  11.         public void Execute()  
  12.         {  
  13.            _bookingRequest.Cancel();  
  14.         }  
  15.     }  
  16. }  
BookingRequest Class,
  1. using System;  
  2. using CabScheduling.BookingModel;  
  3.   
  4. namespace CabScheduling.CabBooking  
  5. {  
  6.     public class BookingRequest {  
  7.   
  8.         public CabBookingModel CabBookingModel { getset; }  
  9.     
  10.         public void Book() {  
  11.             Console.WriteLine("\n{0} Cab Book for Time {1}", CabBookingModel.CabName, CabBookingModel.BookingTimeScheduled);  
  12.             Console.WriteLine("\n{0} Cab Book for Time {1} is Arriving", CabBookingModel.CabName, CabBookingModel.BookingTimeScheduled);  
  13.         }  
  14.   
  15.         public void Cancel() {  
  16.             Console.WriteLine("\n{0} Cab cancelled for Time {1}", CabBookingModel.CabName, CabBookingModel.BookingTime);  
  17.         }  
  18.     }  
  19. }  
BookingService Class,
  1. using System.Collections.Generic;  
  2. using System.Linq;  
  3. using CabScheduling.CabScheduler;  
  4.   
  5. namespace CabScheduling.CabBooking  
  6. {  
  7.     public class BookingService  
  8.     {  
  9.         public readonly List<BookCab> BookedCabList = new List<BookCab>();  
  10.         public readonly List<CancelCab> CanceledCabList = new List<CancelCab>();  
  11.         private readonly ICabScheduler cabScheduler = new CabScheduler.CabScheduler();  
  12.   
  13.         public void ScheduleCab(BookCab cabService)  
  14.         {  
  15.             BookedCabList.Add(cabService);  
  16.         }  
  17.   
  18.         public void CancelCab(CancelCab cabService)  
  19.         {  
  20.             CanceledCabList.Add(cabService);  
  21.         }  
  22.   
  23.         public void ConfirmService(bool booking) {  
  24.             if (booking) {  
  25.                 foreach (var bookingItem in BookedCabList)  
  26.                 {  
  27.                     bookingItem.Execute();  
  28.                     cabScheduler.StartCabScheduler(bookingItem._bookingRequest.CabBookingModel);  
  29.                 }  
  30.             } else {  
  31.                 foreach (var cancelItem in CanceledCabList)  
  32.                 {  
  33.                     cancelItem.Execute();  
  34.                     var cancelledCabId = cancelItem._bookingRequest.CabBookingModel.CabId;  
  35.                     var removeCab = BookedCabList.FirstOrDefault(e => e._bookingRequest.CabBookingModel.CabId == cancelledCabId);  
  36.                     if (removeCab == null || !BookedCabList.Any()) continue;  
  37.                     cabScheduler.CancelCabScheduler(removeCab._bookingRequest.CabBookingModel);  
  38.                     BookedCabList.Remove(removeCab);  
  39.                 }  
  40.             }  
  41.         }  
  42.     }  
  43. }  
CabBookingModel: A Model Class
  1. using System;  
  2.   
  3. namespace CabScheduling.BookingModel  
  4. {  
  5.     public class CabBookingModel  
  6.     {  
  7.         public string RequestId { getset; }  
  8.   
  9.         public string UserName { getset; }  
  10.   
  11.         public string CabId { getset; }  
  12.   
  13.         public string CabName { getset; }  
  14.   
  15.         public DateTime BookingTime { getset; }  
  16.   
  17.         public DateTime BookingTimeScheduled { getset; }  
  18.     }  
  19. }  
TrackTimerModel : A Model Class for Scheduler
  1. using Timer = System.Timers.Timer;  
  2.   
  3. namespace CabScheduling.BookingModel  
  4. {  
  5.     public class TrackTimerModel  
  6.     {  
  7.         public CabBookingModel CabBookingModel { getset; }  
  8.   
  9.         public Timer ScheduledTimer { getset; }  
  10.     }  
  11. }  
Cab Schedular: Schedular Algorithm used by Command Pattern
 
ICabSchedular Interface,
  1. using CabScheduling.BookingModel;  
  2.   
  3. namespace CabScheduling.CabScheduler  
  4. {  
  5.     public interface ICabScheduler {  
  6.         void StartCabScheduler(CabBookingModel scheduledJob);  
  7.         void CancelCabScheduler(CabBookingModel scheduledJob);  
  8.     }  
  9. }  
CabSchedular class,
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Timers;  
  5. using CabScheduling.BookingModel;  
  6.   
  7. namespace CabScheduling.CabScheduler  
  8. {  
  9.     public class CabScheduler : ICabScheduler  
  10.     {  
  11.         private readonly List<TrackTimerModel> allTimers = new List<TrackTimerModel>();  
  12.   
  13.         public void StartCabScheduler(CabBookingModel scheduledJob)  
  14.         {  
  15.             var cabTimer = new Timer();  
  16.             var tickTime = (scheduledJob.BookingTimeScheduled - DateTime.Now).TotalMilliseconds;  
  17.             cabTimer.Elapsed += (sender, e) => OnTimedEvent(sender, e, scheduledJob);  
  18.             cabTimer.Interval = tickTime;  
  19.             cabTimer.Enabled = true;  
  20.             allTimers.Add(new TrackTimerModel { CabBookingModel = scheduledJob , ScheduledTimer = cabTimer});  
  21.         }  
  22.   
  23.         private void OnTimedEvent(object sender, ElapsedEventArgs e, CabBookingModel scheduledJob)  
  24.         {  
  25.             var source = (Timer)sender;  
  26.             if (source == nullreturn;  
  27.             Console.WriteLine("\n{0} - {1} !!! - Arriving Scheduled Cab At {2}\n", scheduledJob.CabId, scheduledJob.CabName, scheduledJob.BookingTimeScheduled);  
  28.             Console.WriteLine("{0} - {1} - has Cab Arrived", scheduledJob.CabId, scheduledJob.CabName);  
  29.             source.Stop();  
  30.             source.Dispose();  
  31.             if (allTimers.Any()) {  
  32.                 var removeTimer = allTimers.FirstOrDefault(f => f.CabBookingModel.CabId == scheduledJob.CabId);  
  33.                 allTimers.Remove(removeTimer);  
  34.             }  
  35.         }  
  36.   
  37.         public void CancelCabScheduler(CabBookingModel scheduledJob) {  
  38.             if(!allTimers.Any()) return;  
  39.               
  40.             var cancelTimer = allTimers.FirstOrDefault(e => e.CabBookingModel.CabId == scheduledJob.CabId);  
  41.             if (cancelTimer == nullreturn;  
  42.   
  43.             cancelTimer.ScheduledTimer.Stop();  
  44.             Console.WriteLine("*******************************************");  
  45.             Console.WriteLine("\n{0} - {1} !!! - Cancelled Cab, Scheduled for {2}\n", scheduledJob.CabId, scheduledJob.CabName, scheduledJob.BookingTimeScheduled);  
  46.         }  
  47.     }  
  48. }  
Output

Here, I have booked two different cabs and scheduled these for two different times. The output is given below.

Design Patterns & Practices

Now, I will book two cabs and schedule for two different times but I will cancel one cab.

Design Patterns & Practices

Here, I have booked and scheduled two cabs, Sedan Duster and Honda City. But, I have canceled the cab Id 1 Sedan Duster. I have also canceled from scheduler and only cab 2 Honda City arrived on scheduled time.
 
I have attached the complete code. Please refer to the code for more details.
 
Conclusion

Any problem statement can be divided into a small subset of problem statements and these divisions allow us to create a proper design. And Design Pattern plays  an important role for the desigining of robust and extensible applications.