Question

I am having some trouble applying Factory Pattern.

I have a class that I usually call as Product($modelNumber, $wheelCount). But in a part of legacy code that I am refactoring, I do not have $modelNumber, and only have $productID, where the link between {$modelNumber, $productID} is in the database (or in my case I can hardcode it, as I only have a select few products at the moment).

I need to be able to create my class using $productId, but how?

Using Procedural ways I would have a function that does the lookup, and I would put that function in a file, and include that file anywhere where I need to do the lookup. Thus do this:

$modelNumber = modelLookup($productId)
Product($modelNumber, $wheelCount);

But how do I do it using Object Oriented way?

Note: I have posted a more detailed situation here: https://softwareengineering.stackexchange.com/q/233518/119333 and this is where Factory pattern (and other patterns, like interfaces and function pointer passing) were suggested conceptually, but I hit a wall when trying to implement them in PHP. It kind of seems like a simple question, but I think there are several ways to do it and I am a bit lost as to how. And so I need some help.

Was it helpful?

Solution

I provided a conceptual answer to your SRP problem on Programmers Exchange but I think I can demonstrate it here.

What you basically want is some other object that will do the work to get you the model number of given product ID.

class ProductModelNumberProvider {
    public function findByProductId($productId) {
        // The lookup logic...
    }
}

Your factory should provide a setter constructor so it can make use of this object internally to lookup the model number if needed. So basically you will end up with a ProductFactory similar to this.

class ProductFactory {
    private $productModelNumberProvider;
    
    public function __construct(ProductModelNumberProvider $productModelNumberProvider) {
        $this->productModelNumberProvider = $productModelNumberProvider;
    }

    public function getProductByIdAndWheels($productId, $wheels) {
        $modelNumber = $this->productModelNumberProvider($productId);
        return $this->getProductByModelNumberAndWheels($modelNumber, $wheels);
    }

    public function getProductByModelNumberAndWheels($modelNumber, $wheels) {
        // Do your magic here...
        return $product;
    }
}

EDIT

On second thought the setter is not the best approach since having a ProductModelNumberProvider instance is mandatory. That is why I moved it to have it injected through the constructor instead.

OTHER TIPS

I can think of something like this:

$factory = new ProductBuilder();
$factory->buildFromProductId($productId, $wheelCount); //uses modelLookup() internally
$factory->buildFromModelNumber($modelNumber, $wheelCount); //just returns Product()

It is basically creating a class on top of the procedural function, but it does separate the logic of creating the class separately from looking up the mapping.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top