A framework should centralize WebDriver creation/teardown in a factory and, for parallel execution, store the driver in a ThreadLocal so each thread has its own isolated instance. Tests never instantiate the driver directly.
A DriverFactory/DriverManager reads config (browser, headless, grid URL), creates the right WebDriver (Selenium Manager or options), and hands it out; a corresponding teardown quits it. For parallel runs, a static ThreadLocal<WebDriver> gives each thread a separate driver, preventing cross-thread interference (the #1 parallel bug). Tests/pages obtain the driver via DriverManager.getDriver() rather than a shared field. This centralization enables cross-browser switching by config, clean lifecycle management via hooks/@Before-@After, and safe parallelism. Leaking drivers (not quitting) or sharing one across threads are classic framework defects.
DriverFactory.createDriver() reads browser=chrome from config and stores it in ThreadLocal; five parallel threads each get their own Chrome, and @AfterMethod calls driver.quit() and removes the ThreadLocal to prevent leaks.
Your framework works serially but fails randomly when parallelized, with actions hitting the wrong browser. What's the design flaw and fix?