2010-04-06 3 views
5

i utilisé pour créer une instance d'une classe singleton comme ceci:Extension une classe singleton

$Singleton = SingletonClassName::GetInstance(); 

et pour la classe non singleton:

$NonSingleton = new NonSingletonClassName; 

je pense que nous ne devrions pas différencier la façon dont nous créons une instance d'une classe si c'est un singleton ou non. si je regarde dans la perception de l'autre classe, je me fiche de savoir si la classe nous avons besoin d'une classe singleton ou non. donc, je ne suis toujours pas à l'aise avec la façon dont php traite une classe singleton. je pense et je veux toujours écrire:

$Singleton = new SingletonClassName; 

juste une autre classe non singleton, y at-il une solution à ce problème?

+1

Ceci n'est pas une question - vous vous plaignez que vous n'aimez pas comment un motif est fait. -1 –

+1

C'est une question très justifiée. +1 parce que -1 n'est pas: P – Leo

+2

N'utilisez pas PHP? – Kevin

Répondre

2

Je ne le recommanderais pas car cela rendrait votre code beaucoup plus difficile à comprendre (Les gens pensent que de nouveaux moyens un tout nouvel objet). Mais alors je ne voudrais pas recoemmed l'utilisation de Singletons.

L'idée de base de ce code est qu'il existe un wrapper autour d'un singleton. Toutes les fonctions et les variables accessibles via ce wrapper affectent réellement le singleton. Il n'est pas parfait comme le code ci-dessous ne met pas en œuvre un grand nombre de méthodes magiques et les interfaces SPL mais ils peuvent être ajoutés si nécessaire

code

/** 
* Superclass for a wrapper around a singleton implementation 
* 
* This class provides all the required functionality and avoids having to copy and 
* paste code for multiple singletons. 
*/ 
class SingletonWrapper{ 
    private $_instance; 
    /** 
    * Ensures only derived classes can be constructed 
    * 
    * @param string $c The name of the singleton implementation class 
    */ 
    protected function __construct($c){ 
     $this->_instance = &call_user_func(array($c, 'getInstance')); 
    } 
    public function __call($name, $args){ 
     call_user_func_array(array($this->_instance, $name), $args); 
    } 
    public function __get($name){ 
     return $this->_instance->{$name}; 
    } 
    public function __set($name, $value){ 
     $this->_instance->{$name} = $value; 
    } 
} 

/** 
* A test singleton implementation. This shouldn't be constructed and getInstance shouldn't 
* be used except by the MySingleton wrapper class. 
*/ 
class MySingletonImpl{ 
    private static $instance = null; 
    public function &getInstance(){ 
     if (self::$instance === null){ 
      self::$instance = new self(); 
     } 
     return self::$instance; 
    } 

    //test functions 
    public $foo = 1; 
    public function bar(){ 
     static $var = 1; 
     echo $var++; 
    } 
} 

/** 
* A wrapper around the MySingletonImpl class 
*/ 
class MySingleton extends SingletonWrapper{ 
    public function __construct(){ 
     parent::__construct('MySingletonImpl'); 
    } 
} 

Exemples

$s1 = new MySingleton(); 
echo $s1->foo; //1 
$s1->foo = 2; 

$s2 = new MySingleton(); 
echo $s2->foo; //2 

$s1->bar(); //1 
$s2->bar(); //2 
+0

wow, c'est cool. Merci beaucoup ! – cakyus

3

Il vaut mieux être l'inverse - fournir un factory-method pour les non-singletons, et obtenir des instances de les utiliser:

$NonSingleton = NonSingletonClassName::createInstance(); 

C'est une pratique recommandée pour Java (en Effective Java), mais il en va à la plupart des langages orientés objet.

1

Vous ne pouvez pas créer un Singleton de la même manière qu'une instance de classe normale. new retournera toujours une nouvelle instance, donc vous devez avoir le constructeur non-public et donc vous devez avoir un moyen différent de l'appeler à l'intérieur de la classe.

Vous pouvez avoir des méthodes d'usine sur toutes les classes, par ex. faites toujours getInstance() comme indiqué dans une autre réponse. Une autre option serait d'utiliser un Service Locator et un qui sait s'il faut retourner quoi.

1

Basé sur ce mot-clé new signifie que tout ce que vous voulez est sans importance. new crée une nouvelle instance de la classe, c'est pourquoi il a nommé nouveau :-)

+0

ha ha .. vous avez absolument raison :-) – cakyus