Реестр или шаблон 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)