通过构造函数获取引用


PHP Getting a reference through a constructor?

我想知道是否有可能使用关键字'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

第一几个事实:

  • 构造函数不能返回值。
  • $this不能重新分配(它可以在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);

直接将对象引用存储在instances变量中不是更容易吗?

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

只是猜测,但似乎将您的简单整数参数存储为实例缓存的数组键将比存储序列化结构的sha1签名"便宜",即使对象具有相同的初始参数,也可能不相同。