Ik ben al een tijdje bezig met OOP, maar nu is mijn oog gevallen op het Singleton design pattern.
Ik heb een beetje rond gelezen en dacht, hier ga ik eens wat mee uitproberen. Wat ik nu wil, is een singleton database class in meerdere classes kunnen gebruiken. Hoe kan ik dit het beste doen?
De code:
Database.class.php
<?php
class Database {
// Store the single instance of Database
private static $m_pInstance;
private function __construct()
{
echo "Constructor called<br />\n";
}
public static function getInstance()
{
if (!self::$m_pInstance)
{
self::$m_pInstance = new Database();
}
return self::$m_pInstance;
}
public function query()
{
echo "Query is called<br />";
}
}
?>
Maar als ik nu bijvoorbeeld deze database class in meerdere classes wil gebruiken, moet ik dan elke keer als ik een query uit wil voeren die code gebruiken, of kan dit makkelijker?
Met het idee van Martijn werk je als het ware in een soort context. Engine is je context, de 'leefruimte' van je applicatie. Dan vraag ik mij weer af: is dit handig? Komt het voor dat je binnen 1 applicatie verschillende contexten nodig hebt - verschillende engines? Zo niet, dan is singleton volgens mij handiger omdat je zo de constructor vrij houdt voor parameters voor het object zelf. Daarnaast hoef je je dan bij ingewikkeldere constructies (met call_user..., ReflectionClass::newInstance, PDOStatement::fetch(PDO_CLASS)) niet druk te maken over je wel goed meegegeven context.
Je zou ook eens naar het Registery Pattern kunnen kijken. Eigenlijk is dat ongeveer wat Martijn! doet. Echter kan je er ook voor kiezen om alleen het register Singleton te maken, dan heb je en de voordelen van Singleton (geen vooraf vastgelegde argumenten) en de voordelen van Martijn's implementatie (geen Singleton in tal van klassen te hoeven implementeren)
Last but not least:
<?php
class SingletonImplementatie {
static public function instance() {
static $instance;
return $instance ? $instance : $instance = new self();
}
}
?>
Volgens mij de kleinst mogelijke singleton-implementatie in PHP.
Je moet het voorbeeld van mij eigenlijk zien als gereedschapskist van de applicatie.
In de constructor van de engine heb ik (het gereedschap :P):
<?php
$this->oDB = new CMysql;
$this->oUser = new CUser($this);
$this->oStorage = new CStorage;
$this->oCache = new CCache($this);
$this->oCategory = new CCategory($this);
$this->oProduct = new CProduct($this);
$this->oTrolley = new CTrolley($this);
$this->oOrder = new COrder($this);
$this->oForm = new CForm($this);
$this->oMail = new PHPMailer;
?>
Tis een webwinkel ;P
Nu bestaat mijn webwinkel uit diverse acties.
Iedere acties is geimplementeerd als klasse.
Deze erft over van een algemene klasse, waarin algemene zaken voor alle acties worden uitgevoerd.
dus:
<?php
abstract class CAction
{
final function __construct( array $_aConf )
{
$this->oEngine = new CEngine($_aConf);
$this->oTpl = new Stormy;
}
abstract function go();
}
class CAction_view_product extends CAction
{
function go(){}
}
?>
Je hebt de constuctor van je klasse netjes private gemaakt, maar je zal ook de clone methode nog private moeten maken. Anders kan je dmv het clonen van je object als nog twee verschillende instanties krijgen ondanks dat je het singleton pattern gebruikt.