Soyut singleton sınıf uzatın

6 Cevap php

Eğer bir tür yeni nesneler oluşturur ve bu factroy sınıfı bu gibi bir tek bir fabrika sınıfını olsaydı:

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;
    }
}

Aynı kod bazı nesne o kendi fabrika ihtiyacı her zaman tekrarlar. Yani ben bu fabrika sınıfı soyut yapmak ve her fabrika için yalnızca belirli rutinleri uygulamaya karar verdi. Ama PHP soyut sınıf örneğini izin vermez.

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

Ölümcül hata: soyut sınıf Base_Factory örneğini olamaz

Sen ne yapardın?

6 Cevap

PHP yöntemlerde, self, her zaman yöntem tanımlanır grubunu belirtir. Sürüm 5.3.0 beri, PHP, adını ve almak için geçersiz statik yöntemler, hem de işlevi get_called_class() erişmek için static anahtar sözcüğünü kullanabilirsiniz "bağlama geç statik", destekler statik bağlamda türetilmiş bir sınıf.

Ancak, tasarım önemli bir kusuru vardır: statik özelliği $factory Base_Factory türetilen tüm sınıflar arasında paylaşılan tanımlanır. Bu nedenle, bir tek bu özellik oluşturulan ve depolanan ilk kez, diğer tüm aramalar getInstance() olursa olsun, türetilmiş bir sınıf kullanılır ne, aynı nesneyi dönecektir.

Sen tekiz nesnelere statik sözlük haritalama sınıf isimlerini kullanabilirsiniz:

abstract class Base_Factory {
    private static $_instances = array();
    public static function getInstance() {
        $class = get_called_class();
        if (!isset(self::$_instances[$class])) {
            self::$_instances[$class] = new $class();
        }
        return self::$_instances[$class];
    }
}

Oh, bir şey daha: Eğer tekil nesneler, aşırı kullanarak singleton tasarım deseni olması için bir işaret olabilir için yeniden kullanımı kod bir olasılık arıyoruz gerçeği! Eğer tekil olarak uygulamak planlıyoruz sınıfları gerçekten singletons iseniz ve belirli bir sınıfın birden çok örneği isteyebilirsiniz faydası durumda olacak kendinize sorun.

Genellikle bu bağlamda açısından tekil nesneler için erişimcilerini sağlayan mevcut "uygulama bağlamında" temsil eden sadece bir Singleton kullanmak çok daha iyidir.

PHP 5.3 +

abstract class Singleton
{
    /**
     * Instance
     *
     * @var Singleton
     */
    protected static $_instance;

    /**
     * Constructor
     *
     * @return void
     */
    protected function __construct() {}

    /**
     * Get instance
     *
     * @return Singleton
     */
    public final static function getInstance() {
        if (null === static::$_instance) {
            static::$_instance = new static();
        }

        return static::$_instance;
    }
}

PHP> = 5.3 Sadece

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;
    }
}

Bu gibi basit bir sınıf içinde singletons kaydettirin

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

Sonra bunu

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();

Çıktı

aSingleton called 1 times
aSingleton called 2 times

Peki işlevini çağırarak sınıf Base_Factory olmadığından emin olmak için bir kontrol yapabilirdi.

if(__CLASS__!='Base_Factory')

Sonra Geçerli nesnenin yerine mevcut sınıfına başvurmak yerine kendini $ kullanabilirsiniz.

if (!$this->factory)
        $this->factory = new self();
    return $this->factory;

Tanımı soyut classess herhangi bir diğer nesne yönelimli diller gibi PHP örneği olamaz. Yani Base_Factory arayüz yerine soyut bir sınıf olmalıdır.

PHP kılavuzundan: "Bu soyut olarak tanımlanmış bir sınıfın örneğini oluşturmak için izin verilmez."