Domanda

Diciamo che sto scrivendo una classe PHP (>= 5.0) che dovrebbe essere un singleton.Tutti i documenti che ho letto dicono di rendere privato il costruttore della classe in modo che la classe non possa essere istanziata direttamente.

Quindi, se ho qualcosa del genere:

class SillyDB
{
  private function __construct()
  {

  }

  public static function getConnection()
  {

  }
}

Ci sono casi in cui viene chiamato __construct() diverso da quando sto eseguendo a

new SillyDB() 

chiamare all'interno della classe stessa?

E perché mi è consentito creare un'istanza di SillyDB dall'interno di se stesso?

È stato utile?

Soluzione

__construct() verrebbe chiamato solo se lo chiamassi dall'interno di un metodo per la classe contenente il costruttore privato.Quindi per il tuo Singleton, potresti avere un metodo come questo:

class DBConnection
{
   private static $Connection = null;

   public static function getConnection()
   {
      if(!isset(self::$Connection))
      {
         self::$Connection = new DBConnection();
      }
      return self::$Connection;
   }

   private function __construct()
   {

   }
}

$dbConnection = DBConnection::getConnection();

Il motivo per cui puoi/vorresti creare un'istanza della classe dall'interno di se stessa è che puoi verificare che esista solo un'istanza alla volta.Dopotutto, questo è il punto centrale di Singleton.L'utilizzo di un Singleton per una connessione al database garantisce che l'applicazione non effettui molte connessioni DB alla volta.


Modificare: Aggiunto $, come suggerito da @emanuele-del-grande

Altri suggerimenti

Ecco un singleton molto semplice che genera semplicemente una stringa di data/ora:

class TheDate
{
    private static $DateInstance = null;
    private $dateVal;

    public static function getDateInstance()
    {
        if(!isset(self::$DateInstance))
        {
            self::$DateInstance = new TheDate();
        }

        return self::$DateInstance;
    }

    public static function getDateVal()
    {
        return self::$DateInstance->dateVal;
    }

    private function __construct()
    {
        $this->dateVal = strftime("%Y-%m-%d %H:%M:%S");
    }
}

Fare qualcosa del genere ovviamente mi dà sempre la stessa data:

$date1 = TheDate::getDateInstance();
echo $date1->getDateVal() . "<br />";

$date2 = TheDate::getDateInstance();
echo $date2->getDateVal() . "<br />";

E fare questo non genera alcun errore:

class NewDate extends TheDate
{
    public function __construct()
    {

    }
}

OK, ho eseguito alcuni test per conto mio.

  • Se non dichiari il tuo costruttore nella sottoclasse, provare a istanziarlo genererà un errore fatale, perché tenta di chiamare il costruttore della superclasse.
  • Nel caso di una connessione DB, quando presumibilmente stai restituendo (in PHP, comunque) un'istanza mysqli o la risorsa restituita da mysql_connect() funzione (o qualche altro collegamento a qualche altro RDBMS), finché si contrassegna l'istanza come privata, non vi è alcun pericolo che qualcuno la sottoclassi e manometta il collegamento.
  • Come ho accennato prima, se qualcuno vuole davvero sovrascrivere il tuo comportamento e creare più connessioni, potrebbe farlo anche scrivendo una nuova classe.

Prova il codice, Mark, e fammi sapere cosa scopri.

MODIFICARE:Inoltre, in questa particolare situazione, non sono sicuro del motivo per cui dovresti preoccuparti di impedire a una persona di creare sottoclassi.Se qualcuno ha accesso al tuo codice PHP per sottoclassarlo, allora avrà anche accesso al tuo codice per copiarlo e modificare i modificatori di accesso in qualcosa che (per qualsiasi motivo) trova adatto.

L'utilità pratica del Singleton in questo caso è che, utilizzandolo, puoi assicurarti di utilizzare sempre la stessa connessione al database per una determinata richiesta HTTP.Lo realizza.Le altre cose (usando final e costruttori privati) è utile conoscerlo da un punto di vista teorico, e ancora più utile sapere se si desidera distribuire codice di qualità API ad altri programmatori, ma nel caso di questo esempio particolare, tutto ciò che le parole chiave stanno facendo è aggiungere byte a la dimensione del file della tua classe.

Un po' di pignoleria:Per completezza probabilmente lo faresti dichiarare la lezione come definitiva anche dal momento che non vorresti che qualcuno sottoclassasse questa classe e implementasse il proprio costruttore pubblico.

(Perdonami se il compilatore rileva l'override di un costruttore privato, ma non credo che lo faccia)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top