2

内部結果をキャッシュするクラスを実装したいと考えています。これらの結果は、クラスのすべてのインスタンスで同じです。つまり、このキャッシュをすべてのインスタンスで共有するのが賢明かもしれません。

ただし、これらの結果はサブクラスによって異なる場合があります。つまり、キャッシュはサブクラスと共有されません。キャッシュはすべてのサブクラスにも適しているため、メカニズムは継承されます。ただし、各サブクラスは異なる静的配列を使用する必要があります。

この目標を達成するためのさまざまなハックや複雑なパターンを考えることができますが、どれも正気ではないようです。PHP の効率的なパターンを知っている人はいますか?

4

4 に答える 4

4

すべてのサブクラスとアクセサー関数private staticのキャッシュ データを保持する変数の組み合わせは機能するように聞こえますが、それほど複雑ではありません。protected

class Base {
    private static $cache = array();

    protected getCacheItem($key) {
        $type = get_class($this);
        if (!isset(self::$cache[$type])) {
            self::$cache[$type] = array();
        }

        // add checks to taste
        return self::$cache[$type][$key];
    }

    protected function setCacheItem($key, $value) {
        // similar to the above
    }
}

ここから考えると、キャッシュへのアクセスが非常に便利になるように工夫することができます。

class Base {
    private static $cache = array();

    // WARNING! QUESTIONABLE PRACTICE: __get returns by reference
    // Also, overriding __get ONLY might not lead to an intuitive experience
    // As always, documenting non-standard behavior is paramount!
    public function &__get($name) {
        if ($name != 'cache') {
            // error handling
        }

        $type = get_class($this);
        if (!isset(self::$cache[$type])) {
            self::$cache[$type] = array();
        }

        return self::$cache[$type];
    }
}

その後、これを次のように使用できます

$b = new Base;
$b->cache['foo'] = 'bar';

実際に見てください

于 2012-04-20T10:08:37.360 に答える
1

これは私がこれらの回答から抽出したものであり、共有する価値があると思います. コメントするには大きすぎるため、ジョンの回答を大幅に編集したくありませんでした。

このソリューションには使用カウンターがあり、最後のクラス インスタンスが設定解除されたときにキャッシュを解放します。そして、子供たちに手間をかけずに基本クラスから動作するようです。

class A {
  private static $aCacheAll = array();
  protected $aCache;

  function __construct(){
    $type = get_class($this);
    if(!isset(self::$aCacheAll[$type])){
      self::$aCacheAll[$type] = array(0,array());           
    }
    self::$aCacheAll[$type][0]++;
    $this->aCache =& self::$aCacheAll[$type][1];
  }

  function __destruct(){
    $type = get_class($this);
    if(!isset(self::$aCacheAll[$type])) return;
    self::$aCacheAll[$type][0]--;
    if(self::$aCacheAll[$type][0] <= 0){
       unset(self::$aCacheAll[$type]);
       // for testing
       print "Freed memory for $type cache\n";
    }
  }

  /**
   * Brain dead test functions
   */
  function set($x){
    $this->aCache[$x] = 1;
  }

  function get() {
    var_dump($this->aCache);
  }
}

class B extends A {}

/*
 * Test it
 */

$a1 = new A();
print "Empty on start: ";
$a1->get();
$a1->set('a');
print "Set a for A: ";
$a1->get();
$a2 = new A();
print "... and have it in \$a2, too: ";
$a2->get();
$b = new B();
print "But not in B: ";
$b->get();
$b->set('b');
print "Set b for B: ";
$b->get();
print "... is not in A: ";
$a2->get();
unset($a1);
print "Cache is retained, if \$a1 is freed, but vanishes when the final instance is unset: ";
unset($a2);
print "B cache still exists, until the program exits: ";
于 2012-04-20T19:19:43.877 に答える
1

static をまったく使用しないでください。ほとんどの場合、それは正しい解決策ではありません。いくつかのストレージ オブジェクト (場合によってはArrayObject ) を作成し、それをすべてのMyClassインスタンスに渡します。

$sharedStorage = new ArrayObject();
$anotherStorage = new ArrayObject();

$instanceA = new MyClass($sharedStorage);
$instanceB = new MyClass($sharedStorage);

$instnceC = new MySubClass($anotherStorage);

シンプルで、テストやメンテナンスがはるかに簡単です。最も重要なことは、ハックを使用せず、一般的でよく知られている構造のみを使用することです。

そして、それが間違った使い方をしている可能性があることを恐れているなら、例えば:

$instanceA = new MyClass($sharedStroage);
$instanceB = new MyClass($anotherStroage);

新しいオブジェクトの作成を担当するファクトリ クラスを作成します。


ところで、なぜそのような奇妙な要件が必要なのですか? 特定のクラスのすべてのインスタンスに共通のストレージが必要ですが、そのクラスのサブタイプは必要ないのでしょうか?

于 2012-04-20T11:01:00.357 に答える
0

静的クラス変数?

http://php.net/manual/de/language.oop5.static.php

class Test {
  static protected $sharedInClassInstances = array();
  private $myOwnInstanceVariable = array();

  public function __construct() {}
}

のすべてのインスタンスは、他のすべてのインスタンスと共有されているTestにアクセスできる必要があります。Test::$sharedInClassInstances一方$this->myOwnInstanceVariable、単一のオブジェクトでのみ使用できます。

于 2012-04-20T10:06:46.923 に答える