{
    "href": "/post/2015/07/07/a-factory-should-create-not-retain/",
    "relId": "2015/07/07/a-factory-should-create-not-retain",
    "title": "A Factory Should Create, Not Retain",
    "author": "pmjones",
    "markup": "html",
    "tags": [
        {
            "href": "/tag/patterns/",
            "relId": "patterns",
            "title": "Patterns",
            "author": null,
            "created": null,
            "updated": [],
            "markup": "markdown"
        },
        {
            "href": "/tag/php/",
            "relId": "php",
            "title": "PHP",
            "author": null,
            "created": null,
            "updated": [],
            "markup": "markdown"
        },
        {
            "href": "/tag/programming/",
            "relId": "programming",
            "title": "Programming",
            "author": null,
            "created": null,
            "updated": [],
            "markup": "markdown"
        }
    ],
    "created": "2015-07-07 18:06:50 UTC",
    "updated": [
        "2015-07-07 18:06:50 UTC"
    ],
    "html": "<p>In <a href=\"https://www.reddit.com/r/PHP/comments/3bulgq/service_locator_in_controllers/\">a recent Reddit conversation</a>, some of us went off on <a href=\"https://www.reddit.com/r/PHP/comments/3bulgq/service_locator_in_controllers/cspvee5\">a tangent about factories</a>.  I maintained then, and do now, that a \u201cfactory\u201d always-and-only returns a new instance. If you have a \u201cfactory\u201d that returns anything other than a new instance, it\u2019s not a factory alone. In the case of factory methods, it is a factory + accessor; in the case of factory objects, it is a factory + registry.</p>\n<p>A \u201cfactory\u201d (whether a factory method or factory object) is one way to separate object <em>creation</em> from object <em>use</em>.</p>\n<p>Let\u2019s say we need to create an object to do some work in a class method:</p>\n<pre><code class=\"php\">class Example\n{\n    public function __construct($db)\n    {\n        $this-&gt;db = $db;\n    }\n\n    public function doSomething($itemId)\n    {\n        $data = $this-&gt;db-&gt;fetchOne(\n            \"SELECT * FROM items WHERE id = :id\",\n            ['id' =&gt; $itemId]\n        );\n        $item = new Item($data);\n\n        // do some other work with the item,\n        // the return the results of that work.\n        return $results;\n    }\n}\n</code></pre>\n<p>The item <em>creation</em> is mixed in with the <em>use</em> of the item. What we want to do is separate the creation from the usage. One way to do that is to use a factory method, or a factory object, to handle object creation for us. Here\u2019s an example of a factory method:</p>\n<pre><code class=\"php\">class Example\n{\n    public function __construct($db)\n    {\n        $this-&gt;db = $db;\n    }\n\n    public function doSomething($itemId)\n    {\n        $data = $this-&gt;db-&gt;fetchOne(\n            \"SELECT * FROM items WHERE id = ?\",\n            ['id' =&gt; $id]\n        );\n        $item = $this-&gt;item($itemId);\n\n        // do some other work with the item,\n        // the return the results of that work.\n        return $results;\n    }\n\n    public function item($data) // factory method\n    {\n        return new Item($data);\n    }\n}\n</code></pre>\n<p>Here\u2019s an example of an injected factory object:</p>\n<pre><code class=\"php\">class Example\n{\n    public function __construct($db, $factory)\n    {\n        $this-&gt;db = $db;\n        $this-&gt;factory = $factory;\n    }\n\n    public function doSomethingWithItem($id)\n    {\n        $data = $this-&gt;db-&gt;fetchOne(\n            \"SELECT * FROM items WHERE id = ?\",\n            ['id' =&gt; $id]\n        );\n        $item = $this-&gt;factory-&gt;item($data);\n\n        // do some other work with the item,\n        // the return the results of that work.\n        return $results;\n    }\n}\n\nclass Factory // factory object\n{\n    public function item($data) // factory method\n    {\n        return new Item($data);\n    }\n}\n</code></pre>\n<p>There were some folks in the Reddit thread that believe a factory may additionally <em>retain</em> the created instance for reuse. For example, let\u2019s say we create and the reuse a collaborator object of some sort:</p>\n<pre><code class=\"php\">class Example\n{\n    public function doSomething()\n    {\n        $collab = $this-&gt;collab();\n        // do stuff, then:\n        return $result;\n    }\n\n    protected function collab() // factory method?\n    {\n        if (! $this-&gt;collab) {\n            $this-&gt;collab = new Collab();\n        }\n        return $this-&gt;collab;\n    }\n}\n</code></pre>\n<p>As far as I can tell, that\u2019s not just a factory. There are three things going on there: initializing a property, creating an object, and accessing a property. To split the concerns, one would need two methods:</p>\n<pre><code class=\"php\">class Example\n{\n    public function doSomething()\n    {\n        $collab = $this-&gt;getCollab();\n        // do stuff, then:\n        return $result;\n    }\n\n    protected function getCollab() // initialize + access\n    {\n        if (! $this-&gt;collab) {\n            $this-&gt;collab = $this-&gt;newCollab();\n        }\n        return $this-&gt;collab;\n    }\n\n    protected function newCollab() // factory\n    {\n        return new Collab();\n    }\n}\n</code></pre>\n<p>Now the concern of <em>creating</em> the object is represented by <code>newCollab()</code> method, and the concerns of <em>initializing and accessing</em> the property are represented by the <code>getCollab()</code> method. Indeed, splitting out a factory method in this kind of situation is the exact recommendation in the GOF <a href=\"http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612/\">Design Patterns</a> book on page 113; this is the book that defined the term \"factory method\" in the first place, so it seems authoritative on this point.</p>\n<p>What happens when you add retention to what would otherwise be a factory object? For example, is the following <em>only</em> a factory object, or does it do more than just create and return new instances?</p>\n<pre><code class=\"php\">class WhatIsThatThing\n{\n    public function getService()\n    {\n        if (! $this-&gt;service) {\n            $this-&gt;service = $this-&gt;newService();\n        }\n        return $this-&gt;service;\n    }\n\n    public function newService()\n    {\n        return new Service();\n    }\n}\n</code></pre>\n<p>It both creates objects, and retains the created objects. That makes it more than just a factory; it looks more like a container at this point.</p>\n<p>Finally, regarding method names, it seems like it\u2019s best to indicate what to expect as a return result. I default to <code>newInstance()</code> in factory objects that deal with only a single class, and <code>new&lt;Type&gt;()</code> when the factory object creates many different classes.  Using <code>get&lt;Type&gt;()</code> indicates that a pre-existing instance (probably memoized in a property) is being returned.</p>\n<hr>\n<p class=\"reddit-links\">Read the Reddit discussion about this post <a href=\"https://www.reddit.com/r/PHP/comments/3cgavn/a_factory_should_create_not_retain/\">here</a>.</p>\n"
}
