Ik ben me momenteel aan het verdiepen in de verschillende Design Patterns (voornamelijk van GoF) en heb hierover de volgende vraag:
Overal waar ik kijk worden Factories eerst geinstantieerd, waarna de methoden worden aangeroepen. Waarom zou ik een factory niet op een statische manier aanroepen (scheelt code toch?):
Zoals ik het vaak zie:
$factory = new ObjectFactory;
$object = $factory->makeNewObject();
Zoals ik het wil zien:
$object = ObjectFactory::makeNewObject();
Dus waarom gebruikt iedereen de eerste methode, terwijl de tweede methode simpeler lijkt?
Ik ben benieuwd waar jij je 'zoals ik het vaak zie' voorbeeld vandaan haalt? Ik kan alleen maar static voorbeelden tevoorschijn halen, de manier zoals het hoort. (een factory vind ik de enige klasse die static mag zijn)
Frank, er zit ook een levensgroot verschil tussen de vraag van Tim in jou antwoord. Daar vroeg hij namelijk niet naar. Tim vroeg zich af waarom we niet de statische methode gebruiken voor een factory.
Tevens hoort jouw code niet te kloppen, je bent de static keywords vergeten.
Frank, ik ben bang dat je mijn vraag niet goed hebt begrepen. Om een object aan te maken zie ik twee manieren:
A) Zelf een nieuw object aanmaken met "new";
B) Een factory method ( een methode in een class die een instantie van zijn eigen class aanmaakt )
C) Een factory ( een class die verschillende vormen van een object aan kan maken )
Mijn vraag gaat over de laatste methode.
A. Keyword "new":
De welbekende methode:
<?php
class User{
public $name;
public function construct($name){
$this->name = $name;
}
}
$user = new User();
?>
B. Factory Method
Zie ik ook veel:
<?php
class User{
public static function create(){
return new self();
}
}
$user = User::create();
?>
C. Factory
Waar mijn vraag over gaat:
<?php
class User{
public $name;
public function construct($name){
$this->name = $name;
}
}
class UserFactory{
public static function newTimUser(){
return new User("Tim");
}
public function newOtherUser(){
return new User("Other");
}
}
?>
In het laatste codeblok zie je een klasse User en een klasse UserFactory. Nu kan ik op twee manieren een user aanmaken:
C.1. Zoals ik het vaak zie:
<?php
$factory = new UserFactory();
$user = $factory->newOtherUser();
?>
C.2. Zoals ik het graag zou zien:
<?php
$user = UserFactory::newTimUser();
?>
Mijn vraag
Ik hoop dat dit het duidelijker maakt. Mijn vraag is dus, waarom zie ik vaak methode C.1. in plaats van methode C.2.
UserFactory is een class met enkel statische methodes. UserFactory heeft geen constructor, geen eigenschappen, geen nood aan samenwerking tussen methodes...
De toegevoegde waarde van de variabele $factory is nul.
Zolang UserFactory enkel maar blijft doen wat het nu doet, ben ik geneigd te antwoorden: "daar is niet echt een goede reden voor"
Het Factory pattern is in geen manier bedacht voor het geen jij hem gebruikt. Een factory gebruik je als je met 1 mogelijkheid meerdere objecten zou kunnen aanmaken. Bij bijv. een pizzaria:
<?php
switch ($_POST['pizza']) {
case 'salami':
$pizza = new SalamiPizza();
break;
case 'hawai':
$pizza = new HawaiPizza();
break;
default:
$pizza = new MagaritaPizza();
}
?>
Dit verplaats je in OO naar een factory:
<?php
class Pizzaria
{
public function createPizza($type)
{
switch ($_POST['pizza']) {
case 'salami':
$pizza = new SalamiPizza();
break;
case 'hawai':
$pizza = new HawaiPizza();
break;
default:
$pizza = new MagaritaPizza();
}
}
}
?>
In dit geval is hij niet statisch, het is gewoon een methode van de Pizzaria die als Factory dient. Maar je kan in andere gevallen ook wel eens een aparte Factory klasse maken, in dit geval kunnen ze allemaal statisch. De Factory is dan namelijk helemaal geen object, maar een verzameling functies.
Kijk trouwens ook eens naar Dependency Injection en naar een Service Container, dat is de nieuwere versie van Factories.
Nee, een singleton is iets totaal anders Gerard. Een singleton kijk of er al een instance bestaat, zoniet dan maakt hij er eentje. Singleton is een pattern die door vele gehaat wordt, inclusief mijzelf.
Een factory maakt verschillende objecten aan en vaak niet zichzelf. Tevens kopt je code voor geen kant en is dit alles behalve een singleton.
Nee, een singleton is iets totaal anders Gerard. Een singleton kijk of er al een instance bestaat, zoniet dan maakt hij er eentje. Singleton is een pattern die door vele gehaat wordt, inclusief mijzelf.
Een factory maakt verschillende objecten aan en vaak niet zichzelf. Tevens kopt je code voor geen kant en is dit alles behalve een singleton.
In deze situatie, vind het acceptabel om middels een singleton toegang te geven tot een factory. Ik geef toe dat ik niet de klassieke "gang of four" getInstance() gebruik, maar de singleton intent c.q. use case, wordt wel degelijk bereikt. Een groot nadeel is dat polymorfisme van de Factory zelf lastiger wordt, als voordeel krijg je wel het static constructor idee, waarmee je de factory eenmalig kan "instellen". Maar goed, op het einde an de dag, kan je natuurlijk ook gewoon een factory maken die niet static is, en toch telkens een instance maken, of de instance in een "registry" stoppen.
Ik zal nu het code voorbeeld aanpassen om de singleton te fixen, en factory wat duidelijker te maken.