PHP Получение ссылки через конструктор? - PullRequest
1 голос
/ 11 апреля 2011

Мне интересно, возможно ли при использовании ключевого слова 'new' возвращать ссылку на существующий объект вместо нового объекта.И если нет, то как лучше всего избежать сосуществования объектов с одинаковыми параметрами?

У меня есть класс с аргументами в конструкторе.Если я использую аргументы, аналогичные аргументам существующего экземпляра, я бы хотел, чтобы мой новый объект был ссылкой на существующий.Является ли это возможным?Я понимаю, что он отличается от одиночного, так как в этом случае у нас может быть несколько экземпляров одного и того же класса, но не несколько экземпляров, использующих одинаковые параметры.

class myClass{
 public $signature; /* Unique signature for the connection */
 public static $instances = array(); /* Array of references to connection */
 private static function singleton($cfg,$inst){
   $signature = sha1(serialize($cfg));
   foreach ( self::$instances as $obj )
   {
     if ( $obj->signature == $signature )
       return $obj;
   }
   array_push(self::$instances,$inst);
   return true;
 }
 function __construct($myParam){
   if ( is_object(self::singleton($myParam,$this) )
     // Here I'd like $this to become the ref of my existing object
   else
   {
     $this->signature = $myParam;
     // I construct my new object
   }
 }
}
$e1 = new myClass(1);
$e2 = new myClass(2);
$e3 = new myClass(1); // $e3 should be a reference to $e1

Ответы [ 2 ]

4 голосов
/ 11 апреля 2011

Сначала несколько фактов:

  • Конструктор никогда не сможет вернуть значение.
  • $ это не может быть переназначено (это может быть в PHP 4, но не былоне предназначено и не было документов)

Вывод:

  • Использовать фабричные методы или делегирование. *

* Между этими двумя понятиями есть небольшая разница: они используют делегирование $ a! = $ B, но используют фабричные методы $ a === $ b (см. Ниже)

Пример делегирования:

// Declare the delegate that will be wrapped by DelegationClass
// * Only public methods/properties will be accessible
class MyClass {
    public $a;
    public function a($a) {
        echo "This is a(\$a=$a)\n";
    }
}

class MyDelegationClass {
    static protected $_delegation = 'MyClass'; // define the delegate
    static protected $_i = array(); // instances
    protected $_l = null; // delegation link
    public function __construct($n) {
       if (!array_key_exists($n,self::$_i)) {
           // ensures that the instance is always created
           self::$_i[$n] = new self::$_delegation; 
        }
        $this->_l = self::$_i[$n]; // link to delegate
    }
    public function __get($v) {
        return $this->_l->$v; // get property from delegate link
    }
    public function __set($k,$v) {
        return $this->_l->$k = $v; // set property on delegate link
    }
    public function __call($f,$p) {
        // call method on delegate link
        return call_user_func_array(array($this->_l,$f),$p); 
    }
}
// $a != $b, but $a->a === $b->a
$a = new MyDelegationClass(1);
$b = new MyDelegationClass(1);

Пример заводского класса:

class MyFactoryClass {
    static protected $_i = array(); // instances
    public static function newMyClass($n) {
       if (!array_key_exists($n,self::$_i)) {
           // ensures that the instance is always created
           self::$_i[$n] = new MyClass; 
        }
        return self::$_i[$n]; // return instance
    }
}
// $a === $b
$a = MyFactoryClass::newMyClass(1);
$b = MyFactoryClass::newMyClass(1);
2 голосов
/ 11 апреля 2011

Не проще ли будет напрямую хранить ссылки на объекты в вашем instances var?

if (!isset(self::$instances[$myparam])) {
    self::$instances[$myParam] = ... new object here ...;
} else
    return &self::$instances[$myParam];
}

Просто предположите, но кажется, что сохранение вашего простого целочисленного параметра в качестве ключа массива дляКэш экземпляров будет «дешевле», чем хранение сигнатуры sha1 сериализованной структуры, которая потенциально НЕ может быть одинаковой, даже если объект имеет тот же начальный параметр.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...