Domanda

Se avessi una classe factory che crea nuovi oggetti di qualche tipo, e quella classe factroy è un singleton, come questo:

class Database_Factory extends Base_Factory {
    private static $factory;
    private $objects = array();

    public function __get($profile) {
        // check for object and return it if it's created before
    }

    public static function getInstance(){
        if (!self::$factory)
            self::$factory = new self();
        return self::$factory;
    }
}

Lo stesso codice si ripete ogni volta che un oggetto necessita della propria fabbrica. Così ho deciso di rendere astratto questo factory class e implementare solo routine specifiche per ogni factory. Ma PHP non consente di creare un'istanza di classe astratta.

abstract class Base_Factory {
    public static function getInstance(){
        if (!self::$factory)
            self::$factory = new self();
        return self::$factory;
    }
}

Errore irreversibile: impossibile istanziare la classe astratta Base_Factory

Cosa faresti?

È stato utile?

Soluzione

Nei metodi PHP, self si riferisce sempre alla classe in cui è definito il metodo. Dalla versione 5.3.0, PHP supporta & # 8220; late static binding & # 8221 ;, dove è possibile utilizzare la parola chiave static per accedere ai metodi statici sovrascritti, nonché la funzione get_called_class () per ottenere il nome della classe derivata in un contesto statico.

Tuttavia, il tuo progetto presenta un grosso difetto: la proprietà statica $ factory definita in Base_Factory è condivisa tra tutte le classi derivate. Pertanto, la prima volta che un singleton viene creato e archiviato in questa proprietà, tutte le altre chiamate a getInstance () restituiranno lo stesso oggetto, indipendentemente dalla classe derivata utilizzata.

È possibile utilizzare un dizionario statico che associa i nomi delle classi agli oggetti singleton:

abstract class Base_Factory {
    private static 

Nei metodi PHP, self si riferisce sempre alla classe in cui è definito il metodo. Dalla versione 5.3.0, PHP supporta & # 8220; late static binding & # 8221 ;, dove è possibile utilizzare la parola chiave static per accedere ai metodi statici sovrascritti, nonché la funzione get_called_class () per ottenere il nome della classe derivata in un contesto statico.

Tuttavia, il tuo progetto presenta un grosso difetto: la proprietà statica $ factory definita in Base_Factory è condivisa tra tutte le classi derivate. Pertanto, la prima volta che un singleton viene creato e archiviato in questa proprietà, tutte le altre chiamate a getInstance () restituiranno lo stesso oggetto, indipendentemente dalla classe derivata utilizzata.

È possibile utilizzare un dizionario statico che associa i nomi delle classi agli oggetti singleton:

<*>

Oh, un'altra cosa: il fatto che stai cercando la possibilità di riutilizzare il codice per gli oggetti singleton potrebbe essere un indizio del fatto che stai usando troppo il modello di progettazione singleton! Chiediti se le classi che stai pianificando di implementare come singoli sono davvero singoli e se non ci saranno casi d'uso in cui potresti voler avere più istanze della classe particolare.

Spesso è molto meglio usare un solo singleton che rappresenta l'attuale contesto applicativo & # 8220; & # 8221; che fornisce accessori per oggetti che sono singoli rispetto a questo contesto.

instances = array(); public static function getInstance() { $class = get_called_class(); if (!isset(self::

Nei metodi PHP, self si riferisce sempre alla classe in cui è definito il metodo. Dalla versione 5.3.0, PHP supporta & # 8220; late static binding & # 8221 ;, dove è possibile utilizzare la parola chiave static per accedere ai metodi statici sovrascritti, nonché la funzione get_called_class () per ottenere il nome della classe derivata in un contesto statico.

Tuttavia, il tuo progetto presenta un grosso difetto: la proprietà statica $ factory definita in Base_Factory è condivisa tra tutte le classi derivate. Pertanto, la prima volta che un singleton viene creato e archiviato in questa proprietà, tutte le altre chiamate a getInstance () restituiranno lo stesso oggetto, indipendentemente dalla classe derivata utilizzata.

È possibile utilizzare un dizionario statico che associa i nomi delle classi agli oggetti singleton:

<*>

Oh, un'altra cosa: il fatto che stai cercando la possibilità di riutilizzare il codice per gli oggetti singleton potrebbe essere un indizio del fatto che stai usando troppo il modello di progettazione singleton! Chiediti se le classi che stai pianificando di implementare come singoli sono davvero singoli e se non ci saranno casi d'uso in cui potresti voler avere più istanze della classe particolare.

Spesso è molto meglio usare un solo singleton che rappresenta l'attuale contesto applicativo & # 8220; & # 8221; che fornisce accessori per oggetti che sono singoli rispetto a questo contesto.

instances[$class])) { self::

Nei metodi PHP, self si riferisce sempre alla classe in cui è definito il metodo. Dalla versione 5.3.0, PHP supporta & # 8220; late static binding & # 8221 ;, dove è possibile utilizzare la parola chiave static per accedere ai metodi statici sovrascritti, nonché la funzione get_called_class () per ottenere il nome della classe derivata in un contesto statico.

Tuttavia, il tuo progetto presenta un grosso difetto: la proprietà statica $ factory definita in Base_Factory è condivisa tra tutte le classi derivate. Pertanto, la prima volta che un singleton viene creato e archiviato in questa proprietà, tutte le altre chiamate a getInstance () restituiranno lo stesso oggetto, indipendentemente dalla classe derivata utilizzata.

È possibile utilizzare un dizionario statico che associa i nomi delle classi agli oggetti singleton:

<*>

Oh, un'altra cosa: il fatto che stai cercando la possibilità di riutilizzare il codice per gli oggetti singleton potrebbe essere un indizio del fatto che stai usando troppo il modello di progettazione singleton! Chiediti se le classi che stai pianificando di implementare come singoli sono davvero singoli e se non ci saranno casi d'uso in cui potresti voler avere più istanze della classe particolare.

Spesso è molto meglio usare un solo singleton che rappresenta l'attuale contesto applicativo & # 8220; & # 8221; che fornisce accessori per oggetti che sono singoli rispetto a questo contesto.

instances[$class] = new $class(); } return self::

Nei metodi PHP, self si riferisce sempre alla classe in cui è definito il metodo. Dalla versione 5.3.0, PHP supporta & # 8220; late static binding & # 8221 ;, dove è possibile utilizzare la parola chiave static per accedere ai metodi statici sovrascritti, nonché la funzione get_called_class () per ottenere il nome della classe derivata in un contesto statico.

Tuttavia, il tuo progetto presenta un grosso difetto: la proprietà statica $ factory definita in Base_Factory è condivisa tra tutte le classi derivate. Pertanto, la prima volta che un singleton viene creato e archiviato in questa proprietà, tutte le altre chiamate a getInstance () restituiranno lo stesso oggetto, indipendentemente dalla classe derivata utilizzata.

È possibile utilizzare un dizionario statico che associa i nomi delle classi agli oggetti singleton:

<*>

Oh, un'altra cosa: il fatto che stai cercando la possibilità di riutilizzare il codice per gli oggetti singleton potrebbe essere un indizio del fatto che stai usando troppo il modello di progettazione singleton! Chiediti se le classi che stai pianificando di implementare come singoli sono davvero singoli e se non ci saranno casi d'uso in cui potresti voler avere più istanze della classe particolare.

Spesso è molto meglio usare un solo singleton che rappresenta l'attuale contesto applicativo & # 8220; & # 8221; che fornisce accessori per oggetti che sono singoli rispetto a questo contesto.

instances[$class]; } }

Oh, un'altra cosa: il fatto che stai cercando la possibilità di riutilizzare il codice per gli oggetti singleton potrebbe essere un indizio del fatto che stai usando troppo il modello di progettazione singleton! Chiediti se le classi che stai pianificando di implementare come singoli sono davvero singoli e se non ci saranno casi d'uso in cui potresti voler avere più istanze della classe particolare.

Spesso è molto meglio usare un solo singleton che rappresenta l'attuale contesto applicativo & # 8220; & # 8221; che fornisce accessori per oggetti che sono singoli rispetto a questo contesto.

Altri suggerimenti

PHP 5.3+

abstract class Singleton
{
    /**
     * Instance
     *
     * @var Singleton
     */
    protected static 

PHP 5.3+

<*>instance; /** * Constructor * * @return void */ protected function __construct() {} /** * Get instance * * @return Singleton */ public final static function getInstance() { if (null === static::

PHP 5.3+

<*>instance) { static::

PHP 5.3+

<*>instance = new static(); } return static::

PHP 5.3+

<*>instance; } }

PHP > = 5.3 solo

abstract class Base_Factory {
    protected static $factory;
    public static function getInstance(){
        if (!self::$factory) {
            $class = get_called_class();
            self::$factory = new $class();
        }
        return self::$factory;
    }
}

Registra i tuoi singoli in una lezione semplice come questa

class Singletons {
    static private $singleton = array();
    public function getSingleton($class) {
    if (!isset(self::$singleton[$class])) {
        self::$singleton[$class] = new $class;
    }
    return self::$singleton[$class];
    }
}

Quindi fai questo

class aSingleton {
    public $i;
    public function test() {
    ++$this->i;
    echo get_class() . " called {$this->i} times\n";
    }
}

Singletons::getSingleton('aSingleton')->test();
Singletons::getSingleton('aSingleton')->test();

Output

aSingleton called 1 times
aSingleton called 2 times

Per definizione la classe astratta non può essere istanziata in PHP come nessun altro linguaggio orientato agli oggetti. Quindi Base_Factory dovrebbe essere interfaccia anziché classe astratta.

Dal manuale di PHP: " Non è consentito creare un'istanza di una classe che è stata definita come astratta. "

Bene, puoi fare un controllo per assicurarti che la classe che chiama la funzione non sia Base_Factory.

if(__CLASS__!='Base_Factory')

Quindi usa $ this invece di self per fare riferimento all'oggetto corrente invece che alla classe corrente.

if (!$this->factory)
        $this->factory = new self();
    return $this->factory;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top