Ich habe kürzlich ThinkPHP5 gelernt und zum ersten Mal TestClass::instance() gesehen, eine Methode, die eine TestClass-Instanz erstellen kann. Ich war sehr neugierig und habe den Quellcode von ThinkPHP durchgesehen und im Allgemeinen verstanden, dass die Designideen sehr fortgeschritten sind.
Bauen Sie wieder ein Auto von Grund auf (der Autobau von gestern: eine einfache Implementierung der Array-Parameter-Übergabemethode von AngularJS http://www.miaoqiyuan.cn/p/an...), lassen Sie uns über die spezifische Implementierung sprechen. Dieser Artikel (eine einfache Implementierung der thinkphp5-Instanz) ist ein Originalartikel. Die Originaladresse lautet: http://www.miaoqiyuan.cn/p/ph.... Bitte geben Sie beim Nachdruck die Quelle an.
Alte Regel, direkt zum Code gehen:
<?php class TestClass { public static function instance() { return new self(); } public $data = []; public function __set($name, $val) { return $this->data[$name] = $val; } public function __get($name) { return $this->data[$name]; } } $app1 = TestClass::instance(); $app1->key = 'Application 1'; echo $app1->key . '<br />'; ?>
Um den Aufruf zu erleichtern, habe ich auch ThinkPHP nachgeahmt und eine Hilfsfunktion geschrieben
<?php function app() { return TestClass::instance(); } $app2 = app(); $app2->key = 'Application 2'; echo $app2->key . '<br />'; ?>
Auf diese Weise wird die Instanz einfach implementiert.
Bei dieser Methode gibt es jedoch ein kleines Problem. Stellen Sie sich Folgendes vor: Wenn Sie es 100 Mal aufrufen, müssen Sie 100 Instanzen erstellen.
Fügen Sie der Testklasse ein statisches Attribut hinzu und speichern Sie die erstellte Instanz hier. Wenn Sie es das nächste Mal aufrufen müssen, rufen Sie diese Instanz direkt auf.
<?php class TestClass { public static $instance; //用于缓存实例 public $data = []; public static function instance() { //如果不存在实例,则返回实例 if (empty(self::$instance)) { self::$instance = new self(); } return self::$instance; } public function __set($name, $val) { return $this->data[$name] = $val; } public function __get($name) { return $this->data[$name]; } } function app($option = []) { return TestClass::instance($option); } header('content-type:text/plain'); $result = []; $app1 = app(); $app1->key = "Application 1"; //修改 key 为 Application 1 $result['app1'] = [ 'app1' => $app1->key, //实例中 key 为 Application 1 ]; // 创建 app2,因为 instance 已经存在实例,直接返回 缓存的实例 $app2 = app(); $result['app2'] = [ 'setp1' => [ 'app1' => $app1->key, // Application 1 'app2' => $app2->key, //因为直接调用的实例的缓存,所以 key 也是 Application 1 ], ]; // 无论 app1,app2 都对在内存中 对应的同一个实例,无论通过谁修改,都能改变值 $app1->key = "Application 2"; $result['app2']['setp2'] = [ 'app1' => $app1->key, // Application 2 'app2' => $app2->key, // Application 2 ]; print_r($result); ?>
Durch das obige Experiment können Sie sehen, dass unabhängig von der Häufigkeit des Aufrufs dieselbe Instanz verwendet wird. Dies löst das Problem der geringen Effizienz.
Bisher erfüllt es grundsätzlich die meisten Situationen. Der einzige kleine Fehler besteht darin, dass die Anfangsparameter der Instanzen unterschiedlich sein können, sodass es nicht flexibel aufgerufen werden kann (normalerweise ruft dasselbe Programm zwei Datenbanken auf). Dies kann durch eine leichte Modifikation des obigen Beispiels gelöst werden, indem die eingehenden Parameter als Schlüssel verwendet und die unvernünftigen Instanzen in einem Array zwischengespeichert werden.
<?php class TestClass { public static $instance = []; //用于缓存实例数组 public $data = []; public function __construct($opt = []) { $this->data = $opt; } public static function instance($option = []) { // 根据传入的参数 通过 serialize 转换为字符串,md5 后 作为数组的 key $instance_id = md5(serialize($option)); //如果 不存在实例,则创建 if (empty(self::$instance[$instance_id])) { self::$instance[$instance_id] = new self($option); } return self::$instance[$instance_id]; } public function __set($name, $val) { return $this->data[$name] = $val; } public function __get($name) { return $this->data[$name]; } } function app($option = []) { return TestClass::instance($option); } header('content-type:text/plain'); $result = []; //传入 初始数据 $app1 = app(['key' => '123']); $result['init'] = $app1->key; // 使用 传入的数据,即:123 $app1->key = "app1"; $result['app'] = $app1->key; // 现在值改为了 自定义的 app1了 print_r($result); $result = []; // 创建 app2,注意 初始参数不一样 $app2 = app(); // 因为初始参数不一样,所以还是创建新的实例 $app2->key = "app2"; $result['app1'] = $app1->key; // app1 $result['app2'] = $app2->key; // app2 print_r($result); $result = []; // 创建 app3,传入的参数 和 app1 一样,所以会直接返回 和app1相同 的 实例 $app3 = app(['key' => '123']); $result['log'] = [ 'app1' => $app1->key, // app1 'app2' => $app2->key, // app2 'app3' => $app3->key, // app1 ]; // 设置 app3 的key,会自动修改 app1 的值,因为他们两个是同一个实例 $app3->key = 'app3'; $result['app3_set'] = [ 'app1' => $app1->key, // app3 'app2' => $app2->key, // app2 'app3' => $app3->key, // app3 ]; // 同理,设置 app1 的key,app3 的 key 也会修改 $app1->key = 'app1'; $result['app1_set'] = [ 'app1' => $app1->key, // app1 'app2' => $app2->key, // app2 'app3' => $app3->key, // app1 ]; print_r($result); ?>