Search code examples
phpoopdesign-patternsfactoryfactory-pattern

Factory Method: Prevent a class from Direct Instancing


I have a Factory Method to instance a class. Is there a way to prevent this class from direct instancing?

The only option I see is to use an argument passed into the __construct(), but that's not something I'm looking for.

On the other hand, making the __construct() private would be ideal, but I don't want MyClass to extend the Factory without actual need.

What do you guys think?

Factory Method:

class Factory
{
    public static function instance()
    {
        return new MyClass(true);
    }
}

MyClass:

class MyClass
{
    public function __construct($isFactory = false)
    {
        if (!$isFactory) {
            throw new Exception('Use Factory::instance() to create an object');
        }
    }
}

Solution

  • There are hacks to do that:

    • abusing inheritance to use a protected constructor
    • putting the factory method inside the class so that it can call the private constructor, which is actually not a hack. But then why not using the constructor in the first place?
    • using reflection to access the private constructor

    I'm not promoting anything of that. What I personally do is documenting the API with things like @internal and leave it to the client following that contract.