Factories are simply convenience handling to let you build based on configuration data instead of hard coded structural data.
They only have real value if both ClassA and ClassB have a common ancestor (whilst used in a hard coded fashion like this). These objects should interface a specific type so that both can be used generically as that type. This way it doesn't matter which you get, so long as you get something that can be understood. Something like a storage engine would use a factory to construct its type based on a common interface. So if I made an IStorage interface and then wrote drivers for SQLServer, MySQLi, PDO, binary data files, XML, whatever, it doesn't make a difference what the work it does is, I know that I can ask the result of the factory for the $obj->query() method. It would be up to the drivers to do what they need to do, and give me something back that would be consistent regardless of the driver.
If they don't share a common interface or ancestor class, then its usefulness is literally a "convenience" and nothing more. I use convenience loosely here; I don't believe any IDE would be able to detect what that type of object is based on string input, and therefore would have no way to provide autocompletion. At least with common interface I can typehint the returns off of it and my IDE can continue with autocompletion on the results.