我正在尝试保存每个唯一的类实例,但是当有参数传递给构造函数时需要知道如何执行此操作:
class SingleInstance {
private static $instances = [];
public static function load($class, $args=null) {
if ($args) {
$args = implode(', ', $args); // Array to string (is this the best way?)
}
if (array_key_exists($class, self::$instances)) {
return self::$instances[$class];
}
self::$instances[$class] = new $class($args);
return self::$instances[$class];
}
}
上面的问题是如果我想保存同一个类的两个实例,第一个实例总是唯一一个保存...
class Words {
private $word;
public function __construct($word) {
$this->word = $word;
}
public function show() {
return $this->word;
}
}
$a = SingleInstance::load('Words', ['Dog']);
echo $a->show(); // "Dog"
$b = SingleInstance::load('Words', ['Cat']);
echo $b->show(); // "Dog" because the arguments from the last instance was saved
如何修改SingleInstance
类,以便保存包含发送给构造函数的不同参数的每个实例?
答案 0 :(得分:0)
这是让您的代码“正常工作”的一种方法。 - 据我们所知,直到现在。
// in class SingleInstance
//..
public static function load($class, $args=null) {
if ($args) {
$args = implode(', ', $args); // Array to string (is this the best way?)
}
if (array_key_exists($class, self::$instances)) {
// also check for the value, which is the only difference between the instances so far.
$x=self::$instances[$class];
if($x->show() == $args) {
return self::$instances[$class];
}
}
self::$instances[$class] = new $class($args);
return self::$instances[$class];
}
//..
将导致DogCat
(包含原始代码的其余部分)
但对我来说,最终目标不是很明确,所以很难判断这是否是正确的方法。
答案 1 :(得分:0)
我和@Jeff一起,有点不清楚你要做什么。您可以将array_key_exists()
替换为in_array()
,并检查新实例是否包含在$instances
数组中(显然不相同,但具有相同属性的实例,这就是我们为什么不# 39;在in_array()
)中使用严格的比较。
然后,您可以在缓存中保存具有不同参数的所有实例,只要在数组中找到一个,就返回它。
<?php
class SingleInstance
{
private static $instances = [];
public static function load($class, $args = null)
{
if ($args) {
$args = implode(', ', $args);
}
$c = new $class($args);
if (in_array($c, self::$instances)) {
echo "Hit!";
return self::$instances[$class];
}
self::$instances[$class] = $c;
return self::$instances[$class];
}
}
class Words
{
private $word;
public function __construct($word) {
$this->word = $word;
}
public function show() {
return $this->word;
}
}
$a = SingleInstance::load('Words', ['Dog']);
echo $a->show().PHP_EOL;
$b = SingleInstance::load('Words', ['Cat']);
echo $b->show().PHP_EOL;
$c = SingleInstance::load('Words', ['Cat']);
echo $c->show().PHP_EOL;
这样做的缺点是你正在尝试做某种缓存,因为你无论如何都要实例化这个类,以便测试你是否已经拥有它,这是没有价值的。
如果 某种缓存,那么你可以尝试计算一个类的校验和。名称和参数并将其用作键(在这种情况下,您可以保留初始array_key_exists()
调用):
<?php
class SingleInstance
{
private static $instances = [];
public static function load($class, $args = null)
{
if ($args) {
$args = implode(', ', $args);
}
$checksum = md5($class.$args);
if (array_key_exists($checksum, self::$instances)) {
echo "Hit!";
return self::$instances[$checksum];
}
self::$instances[$checksum] = new $class($args);
return self::$instances[$checksum];
}
}
class Words
{
private $word;
public function __construct($word) {
$this->word = $word;
}
public function show() {
return $this->word;
}
}
$a = SingleInstance::load('Words', ['Dog']);
echo $a->show().PHP_EOL;
$b = SingleInstance::load('Words', ['Cat']);
echo $b->show().PHP_EOL;
$c = SingleInstance::load('Words', ['Cat']);
echo $c->show().PHP_EOL;
关于你在评论中的第一个问题,这段代码仅使用一个参数,但它会更多地破解。要解决此问题,请使用argument unpacking:
<?php
class SingleInstance
{
private static $instances = [];
public static function load($class, $args = null)
{
$checksum = md5($class.implode(', ', $args));
if (array_key_exists($checksum, self::$instances)) {
echo "Hit!";
return self::$instances[$checksum];
}
self::$instances[$checksum] = new $class(... $args); // argument unpacking
return self::$instances[$checksum];
}
}
class Words
{
private $word;
private $word2;
public function __construct($word, $word2) {
$this->word = $word;
$this->word2 = $word2;
}
public function show() {
return $this->word." ".$this->word2;
}
}
$a = SingleInstance::load('Words', ['Dog', 'Word1']);
echo $a->show().PHP_EOL;
$b = SingleInstance::load('Words', ['Cat', 'Word2']);
echo $b->show().PHP_EOL;
$c = SingleInstance::load('Words', ['Cat', 'Word2']);
echo $c->show().PHP_EOL;