|
| 1 | +# When To Use Factories vs Abstract Factories |
| 2 | + |
| 3 | +Starting with version 3, `Zend\ServiceManager\Factory\AbstractFactoryInterface` |
| 4 | +extends `Zend\ServiceManager\Factory\FactoryInterface`, meaning they may be used |
| 5 | +as either an abstract factory, or mapped to a specific service name as its |
| 6 | +factory. |
| 7 | + |
| 8 | +As an example: |
| 9 | + |
| 10 | +```php |
| 11 | +return [ |
| 12 | + 'factories' => [ |
| 13 | + SomeService::class => AnAbstractFactory::class, |
| 14 | + ], |
| 15 | +]; |
| 16 | +``` |
| 17 | + |
| 18 | +Why would you choose one approach over the other? |
| 19 | + |
| 20 | +## Comparisons |
| 21 | + |
| 22 | +Approach | Pros | Cons |
| 23 | +---------------- | -------------- | ---- |
| 24 | +Abstract factory | One-time setup | Performance; discovery of code responsible for creating instance |
| 25 | +Factory | Performance; explicit mapping to factory responsible | Additional (duplicate) setup |
| 26 | + |
| 27 | +Essentially, it comes down to *convenience* versus *explicitness* and/or |
| 28 | +*performance*. |
| 29 | + |
| 30 | +## Conveneience |
| 31 | + |
| 32 | +Writing a factory per service is time consuming, and, particularly in early |
| 33 | +stages of an application, can distract from the actual business of writing the |
| 34 | +classes and implementations; in addition, since requirements are often changing |
| 35 | +regularly, this boiler-plate code can be a nuisance. |
| 36 | + |
| 37 | +In such situations, one or more abstract factories — such as the |
| 38 | +[ConfigAbstractFactory](../config-abstract-factory.md) or the |
| 39 | +[zend-mvc LazyControllerAbstractFactory](https://docs.zendframework.com/zend-mvc/cookbook/automating-controller-factories/) |
| 40 | +— that can handle the bulk of your needs are often worthwhile, saving you |
| 41 | +time and effort as you code. |
| 42 | + |
| 43 | +## Explicitness |
| 44 | + |
| 45 | +The drawback of abstract factories is that lookups by the service manager take |
| 46 | +longer, and increase based on the number of abstract factories in the system. |
| 47 | +The service manager is optimized to locate *factories*, as it can do an |
| 48 | +immediate hash table lookup; abstract factories involve: |
| 49 | + |
| 50 | +- Looping through each abstract factory |
| 51 | + - invoking its method for service location |
| 52 | + - if the service is located, using the factory |
| 53 | + |
| 54 | +This means, internally: |
| 55 | + |
| 56 | +- a hash table lookup (for the abstract factory) |
| 57 | +- invocation of 1:N methods for discovery |
| 58 | + - which may contain additional lookups and/or retrievals in the container |
| 59 | +- invocation of a factory method (assuming succesful lookup) |
| 60 | + |
| 61 | +As such, having an explicit map can aid performance dramatically. |
| 62 | + |
| 63 | +Additionally, having an explicit map can aid in understanding what class is |
| 64 | +responsible for initializing a given service. Without an explicit map, you need |
| 65 | +to identify all possible abstract factories, and determine which one is capable |
| 66 | +of handling the specific service; in some cases, multiple factories might be |
| 67 | +able to, which means you additionally need to know the *order* in which they |
| 68 | +will be queried. |
| 69 | + |
| 70 | +The primary drawback is that you also end up with potentially duplicate |
| 71 | +information in your configuration: |
| 72 | + |
| 73 | +- Multiple services mapped to the same factory. |
| 74 | +- In cases such as the `ConfigAbstractFactory`, additional configuration |
| 75 | + detailing how to create the service. |
| 76 | + |
| 77 | +## Tradeoffs |
| 78 | + |
| 79 | +What it comes down to is which development aspects your organization or project |
| 80 | +favor. Hopefully the above arguments detail what tradeoffs occur, so you may |
| 81 | +make an appropriate choice. |
| 82 | + |
| 83 | +> ### Tooling |
| 84 | +> |
| 85 | +> We will likely provide tooling in the future to convert |
| 86 | +> `ConfigAbstractFactory` configuration into discrete factory classes in the |
| 87 | +> future, allowing you to mitigate the performance issues of using an abstract |
| 88 | +> factory when in production. As such, tooling support should also be a |
| 89 | +> consideration when deciding on your project strategy. |
0 commit comments