2

Let's say you have a string $action run-time, that specifies which type of $object needs to be created: $dbobject, $memcacheobject, $fileobject, $xmlobject, etc. Assume also, that creation of an object is non-trivial and a $factory is required.

Obviously, different object types depend on different things, one on PDO, another on Memcache and so on. So how should I create an object in this conditions? I'm left with a few options:

  1. Create a switch ($action) {} outside of a factory in order to call different subclasses of my factory, which will call it's type of object, for example: case 'db': $obj = new DBFactory($dbh); break;.

    This is clearly bad, since this switch have to be present everywhere where the object is needed.

  2. Have a switch ($action) {} inside some sort of a factory factory, which will do the code in #1. What should then the parent factory depend on, everything it might create? Since it might need database and memcache, in order to follow dependency injection rules you need to supply parent factory with both pdo and memcache instances, even if it won't use them. That also sounds pretty bad.

Another problem is that if I create another object type that depends on something new, then I have to add it's dependencies all over the code where theese factories are instantiated, which is a horizontal change which I should in fact be avoiding. That tells me there is some concept for this problem I don't see right now, therefore the question.

What I'm trying to point out is that even if only the $fileobject is needed, which does not depend on anything, the code that parses $action still needs all dependencies (which is an overkill) or it will instantiace some of them (which is against DI) or needs to reach out to global state/use singletons/registry, which is also considered a bad practice. What would then be a good practice in this situation?

1

You can inject dependencies separately by introducing a registry of factories.

Split you big factory into smaller ones. Each factory only creates one type of the object, and their aggregation - registry, manages them and dispatches creation request. Only needed factories are created (and populated with dependencies) and a caller invokes registry instead of direct access to factory.

This way you can have dependencies only for factories (and type of objects) needed while still being able to use registry in a way you used to.

Beware of runtime failures due to missing factory types, you should ensure that no invocation of registry will request absent factory.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.