PHP:将参数传递给构造函数时保存类实例

时间:2018-03-01 00:02:50

标签: php

我正在尝试保存每个唯一的类实例,但是当有参数传递给构造函数时需要知道如何执行此操作:

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类,以便保存包含发送给构造函数的不同参数的每个实例?

2 个答案:

答案 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;

Demo

这样做的缺点是你正在尝试做某种缓存,因为你无论如何都要实例化这个类,以便测试你是否已经拥有它,这是没有价值的。

如果 某种缓存,那么你可以尝试计算一个类的校验和。名称和参数并将其用作键(在这种情况下,您可以保留初始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;

Demo

关于你在评论中的第一个问题,这段代码仅使用一个参数,但它会更多地破解。要解决此问题,请使用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;

Demo