Реестр или шаблон Singleton в PHP?

Сейчас я работаю с PHP-классами и объектами. В этом вопросе имена полей и методов составлены так, чтобы вы поняли, о чем я говорю.

Это связано с использованием шаблонов проектирования singleton и registry.

Теперь скажем, мне нужно получить доступ к объекту Database, объекту Cache, объектам основных настроек, объекту Session почти в каждом другом классе, который мне нужен, чтобы иметь доступ к ним. SO Я бы использовал реестр для хранения всех 4 этих объектов в один объект класса реестра. Тогда я мог бы просто передать один объект в любой другой объект, который должен получить к ним доступ. Так что это звучит здорово до сих пор, но что, если у меня есть некоторые классы, которым не нужны все 4 из этих объектов, что, если мне ТОЛЬКО нужен доступ к объекту Database или объекту Session в некоторых из моих других классов? Для perfromance было бы лучше всего использовать одноэлемент внутри этих других объектов, или было бы то же самое идти вперед и использовать мой реестр в них?

Я не знаю достаточно хорошо, как объекты работают на PHP, чтобы узнать, будет ли какой-либо результат (меньше использования памяти, использования процессора, времени загрузки).

Таким образом, любой, кто имеет опыт в этом, может сказать мне, будет ли какой-либо выигрыш, используя тот или другой, я нахожусь на том этапе, когда я могу пойти на эфир, не затрагивая время производства или что-то еще. Я бы хотел использовать лучший метод, если могу сейчас.

Ответ 1

Это зависит от вашего приложения. Если вам все еще нужно 3 из 4 классов, то было бы лучше использовать реестр, чем обрабатывать 3 независимо только потому, что вам не нужен четвертый. Загрузка классов лениво будет одним из подходов к уменьшению объема памяти, но тогда вам нужно указать реестр, когда создавать объекты и не сильно отличаться от обработки одиночных пакетов. В качестве альтернативы вы можете создать конструктор n-параметров или использовать массив, чтобы проинструктировать ваш реестр, какие классы должны создавать экземпляры во время построения.

class Registry {
    public $class1;
    public $class2;

    function __construct($uses) {
        foreach($uses as $class) {
            $this->{$class} = new {$class}();
        }
    }

}

Затем создайте экземпляр своего реестра, указав, какие классы необходимо создать.

$reg = new Registry(array('class1'));

Очевидно, вы хотите, чтобы ваш конструктор обрабатывал нулевые параметры для учетной записи для создания экземпляров всех классов по умолчанию.

Ответ 2

Вы можете реализовать ленивую загрузку только для загрузки объектов, которые вам действительно нужны:

class Registry
{
    private static $database = null;

    private static function connectDatabase($key)
    {
        [... do connection stuff ...]
    }

    public static function getDatabase($key)
    {
        if (Registry::$database == null)
        {
            Registry::connectDatabase($key);
        }
        return Registry::$database;
    }
}

Код для регистрации параметров подключения базы данных остается в виде упражнения для читателя.

Ответ 3

Возможно, это правильный шаблон Singleton-Registry. OFC, вы можете реализовать разные вещи, интерфейс SplFixedArray, ArrayAccess и другие. Также неплохо добавить разрушение и уничтожить внутренние объекты, чтобы избежать утечки.

class oRegistry{
   private static $instance = null;

   private $storage = array();

   private function __construct(){}

   private function __clone(){}

   public static function getInstance(){
      if( self::$instance === null ){
         self::$instance = new self();
      }
      return self::$instance;
   }

   public function attach($name, $o) {
      if( true === isset($this->storage[$name]) ) {
          throw new Exception('The instance with name '.$name.' already exists in registry.');
      }
      if( !empty( $name ) ) {
          $this->storage[ $name ] = $o;
      }
   }

   public function detach( $name ){
       if( isset( $this->storage[ $name ] ) ) {
           $this->storage[ $name ] = null;
           unset( $this->storage[ $name ] );
       }
   }

   public function get( $name ){
       if( false === isset( $this->storage[$name] ) ) {
           throw new Exception('Invalid instance requested');
       }
       return $this->storage[ $name ];
   }
}

// usage example
$storage = oRegistry::getInstance();
$obj = new stdClass;
$obj2 = new stdClass;
$obj->test1 = 'test';
$obj2->test2 = 't2';

$storage->attach( 'test1', $obj );
$storage->attach( 'test2', $obj2 );

$got = $storage->get( 'test2' );
var_dump($got); // object(stdClass)#3 (1) { ["test2"]=> string(2) "t2" }

$storage->detach( 'test2' );
$got = $storage->get( 'test2' );
var_dump($got); // bool(false)