IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Singleton sans constructeur privé


Sujet :

Langage PHP

  1. #1
    Membre chevronné
    Avatar de FMaz
    Inscrit en
    Mars 2005
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 643
    Par défaut Singleton sans constructeur privé
    Bonjour à tous.

    Alors voilà, actuellement le schéma que j'utilise pour faire un singleton en PHP est celui-ci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    class ConnexionManager
    {
        private static $instance;
        private $arrConn;
     
        private function __construct()
        {
        	$this->arrConn = array();
        }
     
        public static function getInstance() 
        {
            if (empty(self::$instance))
                self::$instance = new ConnexionManager();
     
            return self::$instance;
        }
     
        public function __clone()
        {
            trigger_error('Le clônage n\'est pas autorisé.', E_USER_ERROR);
        }
     
        // ... le reste est tronqué
    }

    Vous allez dire que je suis peut-être exigeant, mais je trouve un peu désagréable de devoir toujours faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $dbMgr = ConnexionManager::getInstance();
    Au lieu de ce qu'on s'attendrait normalement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    $dbMgr = new ConnexionManager();

    Alors je me suis demandé s'il était possible de rendre le singleton plus... agréable, et j'en suis venu à penser à ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
     
    class ConnexionManager
    {
        private static $instance;
        private $arrConn;
     
        public function __construct() //Constructeur du singleton
        {
            if (!is_object(self::$instance))
            {
                $this->init(func_get_args());
                self::$instance = $this; //L'idée est ici.
            }
            return self::$instance;
        }
     
        public function __clone()
        {
            trigger_error('Le clônage n\'est pas autorisé.', E_USER_ERROR);
        }
     
        private function init($arrParam) //Constructeur de l'objet
        {
             $this->arrConn = array();
        }
        // ... le reste est tronqué
    }


    Cependant, j'ai une sorte de mauvais présentiment, alors je me suis dit que si l'idée était mauvaise, vous aurriez tôt fait de m'indiquer les raisons.


    Alors, vous en pensez quoi ?

  2. #2
    Membre chevronné
    Avatar de FMaz
    Inscrit en
    Mars 2005
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 643
    Par défaut
    Je m'auto-répond:

    1.
    Ca ne fonctionnera pas, car $var = new ConnexionManager() ne va pas prendre la valeur retourné par return, mais la valeur de $this.

    2.
    Il est interdit d'assigner une valeur à $this.


  3. #3
    Membre chevronné
    Avatar de FMaz
    Inscrit en
    Mars 2005
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 643
    Par défaut
    Par contre, ceci fonctionne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
     
    class ConnexionManager
    {
        private static $instance;
        private $arrConn;
     
        public function __construct(&$var) //Constructeur du singleton
        {
            if (!is_object(self::$instance))
            {
                $this->init(func_get_args());
                self::$instance = $this; //L'idée est ici.
            }
            $var = self::$instance;
        }
     
        public function __clone()
        {
            trigger_error('Le clônage n\'est pas autorisé.', E_USER_ERROR);
        }
     
        private function init($arrParam) //Constructeur de l'objet
        {
             $this->arrConn = array();
        }
        // ... le reste est tronqué
    }
    Utilisation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    new ConnexionManager($test1);
    new ConnexionManager($test2);
     
    var_dump($test1 === $test2); //true

    La structure de la classe est certe plus uniforme, mais je ne peux m'empêcher de trouver l'utilisation douteuse.

  4. #4
    Membre Expert Avatar de RunCodePhp
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    2 962
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations forums :
    Inscription : Janvier 2010
    Messages : 2 962
    Par défaut
    Salut

    Mais pas seulement pour ça.
    Sauf erreur, le constructeur ne peut pas contenir de return, le constructeur est juste exécuté (théoriquement).

    En tout cas, tu es vraiment exigeant
    Pour ma part, je ne vois rien de désagréable ou dérangeant à faire un Classe::getInstance()

  5. #5
    Membre chevronné
    Avatar de FMaz
    Inscrit en
    Mars 2005
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 643
    Par défaut
    En fait, ce qui m'agace, c'est que ce n'est pas transparent. Il faut savoir que l'on a affaire à un singleton pour savoir l'utiliser.

    Je trouve plus "normal" que l'utilisation d'un singleton soit exactement la même que celle d'un objet standard. Le comportement interne ne devrait pas concerner le développeur "externe".

  6. #6
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 693
    Par défaut
    Citation Envoyé par FMaz Voir le message
    Je trouve plus "normal" que l'utilisation d'un singleton soit exactement la même que celle d'un objet standard. Le comportement interne ne devrait pas concerner le développeur "externe".
    Sauf que ce n'est pas possible. Le but du singleton étant d'avoir une seule et unique instance, tu ne peux logiquement pas passer par un new.

    Il faut savoir que l'on a affaire à un singleton pour savoir l'utiliser.
    Les doc technique sont là pour ça. Avant d'utiliser une class on regarde la doc pour savoir comment elle marche
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France, Finistère (Bretagne)

    Informations forums :
    Inscription : Juillet 2009
    Messages : 28
    Par défaut
    En noyant le concept de singleton dans une structure fortement objet, on peut arriver à faire comme si ça devenait naturel... je pense à une classe de base, une classe "root" qui implémenterait une méthode "getConnexionManager" et donc héritée par toutes les classes filles ^^

    Après on pourrait peut-être imaginer une classe faite de méthodes abstraites genre "SingletonFactory" et faire des trucs comme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    $conn = SingletonFactory::getConnexionManager();
    $context = SingletonFactory::getContext();
    Tout dépend du contexte :p
    Après c'est vrai que créer une "SingletonFactory" juste pour récupérer un ConnexionManager... ça fait peu.

    bah... dans ce cas "SingletonUtils" qui englobe des choses spécifiques aux singleton ou "Miscellaneous" qui fait un peu de tout... xD

  8. #8
    Membre chevronné
    Avatar de FMaz
    Inscrit en
    Mars 2005
    Messages
    643
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 643
    Par défaut
    Très pertinent...

    En effet, je trouve un peu compliqué de créer une classe Factory pour le singleton. Et en effet, la doc devrait suffire à comprendre.

    Mais j'aurais quand même aimé trouvé une solution transparente pour le développeur.


    Malgré tout, j'espérais qu'il soit possible de trouver un solution avec un new.
    Oui, un new créer une nouvelle "variable", mais j'avais espoir que cette variable pourrait être une sorte de pointeur. (Ce qui n'existe pas en php)

    Enfin, ca m'aura fait comprendre 2-3 trucs au passage, ce qui n'est pas inutile en soit

  9. #9
    Membre éprouvé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 448
    Par défaut
    Citation Envoyé par FMaz Voir le message
    Très pertinent...

    En effet, je trouve un peu compliqué de créer une classe Factory pour le singleton. Et en effet, la doc devrait suffire à comprendre.

    Mais j'aurais quand même aimé trouvé une solution transparente pour le développeur.


    Malgré tout, j'espérais qu'il soit possible de trouver un solution avec un new.
    Oui, un new créer une nouvelle "variable", mais j'avais espoir que cette variable pourrait être une sorte de pointeur. (Ce qui n'existe pas en php)

    Enfin, ca m'aura fait comprendre 2-3 trucs au passage, ce qui n'est pas inutile en soit
    Même sorti du php je n'imagine pas une solution de ce goût là.
    Tu voudrais que l'user space redéfinisse l'adresse de l'espace mémoire nouvellement attribué par le system space, sans que le system space n'en soit informé, puisque tu le fais dans le new qui doit peupler la nouvel adresse mémoire mise à disposition par le system space.

    tu fais un new,
    tu fais un nouvel espace mémoire,
    le new peuple le nouvel espace mémoire disponible.

    Dans ton exemple, ton espace nouvellement créé serait utilisé à mauvais escient puisque sa taille dépasserait largement celle nécessaire à l'affectation d'une référence, en supposant que le compilo laisse faire, et qu'il assigne bien ton espace mémoire avec la référence que tu souhaites.
    Si par ailleurs il se contente de faire pointer le this sur ta référence, il y aurait il me semble une fuite mémoire.
    Puisque lorsque l'on voudra virer $this, c'est un référence du singleton que l'on fera sauter et non l'espace mémoire initialement prévu pour celui ci, qui n'aura plus de lien vers ce $this.

    fin bon cela sort clairement de mes compétences, mais c'est trop alambiqué pour me sembler réalisable, mais c'était intéressant à réfléchir.

    Autrement les références existent en php. Mais pas les pointeurs c'est vrai.

Discussions similaires

  1. [POO] Singletons et constructeurs
    Par oodini dans le forum C++
    Réponses: 3
    Dernier message: 30/10/2008, 14h28
  2. Classe membre sans constructeur par defaut
    Par TheDrev dans le forum C++
    Réponses: 6
    Dernier message: 28/09/2007, 12h13
  3. Réponses: 14
    Dernier message: 17/11/2006, 19h17
  4. [C#] Une classe sans constructeur, ca existe?
    Par legillou dans le forum Windows Forms
    Réponses: 4
    Dernier message: 03/07/2006, 09h58
  5. [JUnit] [Test][Débutant] Constructeur privé
    Par Shabata dans le forum Tests et Performance
    Réponses: 2
    Dernier message: 12/01/2006, 15h45

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo