kohana instance

aleksei5698

Новичок
Здарова народ, вопрос к людям юзавшим kohanu.
Некоторые модули коханы используют примерно такой код(упрощенный):
PHP:
 private static $instances = array(); // коллекция созданных объектов

 public static function instance($name) {
    if (!isset(self::$instances[$name])) {
      $config = Kohana::config('имя модуля')->$name;
      //....
      $obj = new self();           
      self::$instances[$name] = $obj;
    }
    return self::$instances[$name];
  }
Похоже на какую то смесь фабрики с синглтоном.
Статический метод instance('somename') создает (или возвращает ранее созданный) экземпляр объекта с условным именем 'somename' и иницианализирует его из файла конфигурации.

Так вот вопрос - Как называется этот паттерн? Идея мне понравилась, хочу реализовать собственные модули по такому же принципу. Есть ли грабли в его использовании?
 

Adelf

Administrator
Команда форума
А не пофиг как называется? :)
Больше похоже на реестр, умеющий инстанцировать. Фабричный реестр :)
 

aleksei5698

Новичок
))
Хотелось бы немного наговнокодить, вот:

PHP:
class FBTransaction {
  <...>
  public function __construct() {}
  public function setDatabase(FBDataBase $database) {}
  public function setParam($param) {}
  <...>

  private static $instances = array(); // коллекция созданных объектов

  /**
   * Метод создает (или возвращает ранее созданный) экземпляр объекта
   * @return FBQuery
   */
  public static function instance($name = 'default') {
    if (!isset(self::$instances[$name])) {
      self::$instances[$name] = new self();  
      self::$instances[$name]->loadConfig($name);
    } 
    return self::$instances[$name];
  }
  public function loadConfig($name) {
     $config = Kohana::config('fbtransaction')->$name;
     // здесь присоединяем зависимый объект FBDataBase (его настройки тоже загружается из конфига)
     // какую конкретно FBDataBase присоединять задано в $config['db']
     $this->setDatabase(FBDataBase::instance($config['db'])); 
     $this->setParam($config['params']);
  }
}
конфиг fbtransaction.php:
PHP:
return array(
    'tr' => array(
        'db'      => 'default',
        'params'  => IBASE_READ | IBASE_COMMITTED | IBASE_NOWAIT | IBASE_REC_VERSION,
    ),
    'tw' => array(
        'db'      => 'default',
        'params'  => IBASE_WRITE | IBASE_COMMITTED | IBASE_NOWAIT | IBASE_REC_VERSION,
    )
);
теперь чтобы создать транзакцию с названием 'tr' можно написать FBTransaction::instance('tr');
Из плюсов: конфигурация подгружается автоматом, имеем доступ из любой части приложения, не нужны ни какие ServiceLocator-ы
Из минусов - смотрится все через Ж...
Да и еще зависимости классов указываются в конфигах, не пойму пока хорошо это или нет
Собственно интересует - так кто нибудь делает?
 

aleksei5698

Новичок
И еще, если мои модели используют конфиг файлы может их тоже так реализовать?
Или застрелиться сразу пойти? ))
 

Mols

Новичок
aleksei5698
а нафиг нужны именованные транзакции?
имхо перемудрили Вы тут что-то. Разбираться детально лом.
 

Mols

Новичок
aleksei5698
ну я хз. Как по мне, так вроде не нужно это.
Кроме того, везде в приложении надо "помнить" какие именованные объекты уже созданы.
То есть имя объекта в этом реестре имеет некую связь с каким то конфигом.
И если я в одном модуле приложения хочу получить обьект с одним конфигом, а в другом модуле с другим, то я должен помнить о том, что где-то мог быть создан обьект с другим конфигом, но тем же именем, что я хочу использовать здесь.
Теоретически это трудно уловимая коллизия.
Создаёшь обьект в модуле А с именем "мойОбьект" а получаешь обьект созданный в модуле Б но с этим же именем... хз в общем.
Не юзал я кохану другими словами))))
 

AmdY

Пью пиво
Команда форума
я такой паттерн использую, названия вроде бы нет. только у меня одно важное отличие - запоминаю состояние, чтобы можно было работать с последним инстансом, если параметр не передан.
PHP:
class Foo {
 private static $instance = array();
 private static $cursor;
 private function __construct() {
 echo 'Created ' . __CLASS__ . ': ' . self::$cursor;
 }
 private function __clone() {
 }
 public static function getInstance($cursor = 0) {
 if ($cursor !== null) {
 self::$cursor = $cursor;
 }
 if (!array_key_exists(self::$cursor, self::$instance)) {
 self::$instance[self::$cursor] = new self();
 }
 return self::$instance[self::$cursor];
 }
}
Foo::getInstance('test');
Foo::getInstance(); // test
Foo::getInstance(); // 0
 

Mols

Новичок
AmdY
угу.. есть ещё одно отличие. пожалуй поважнее... нет никаких автоматически цепляющихся конфигов.
 

AmdY

Пью пиво
Команда форума
Mols
не, это просто заготовка, в реальности используются и реализации с конфигами, и простые.
 

aleksei5698

Новичок
AmdY,
необходимость работать с последним инстансом, если параметр не передан, я так понимаю вызвана тем что вы в коде класса пишете
PHP:
Foo::getInstance('test');
у НИХ это зовется статической зависимостью
я тоже так сначала хотел, теперь думаю использовать Dependency Injection во время загрузки конфига (выше уже писал об этом)

PHP:
public function loadConfig($name) {
  $this->setFoo(Foo::getInstance('test'));
  //если нужен второй
  $this->setFoo2(Foo::getInstance('otherTest'));
}
в коде класса использовать
PHP:
$this->getFoo()
$this->getFoo2()
А вот теперь что мне больше всегоо покоя не дает, вот тут
PHP:
$this->setFoo(Foo::getInstance('test'));
я явно задаю имя 'test'
Если это имя тоже вынести в конфиг, а?
PHP:
$this->setFoo(Foo::getInstance($config['foo']));
$this->setFoo2(Foo::getInstance($config['foo2']));
 

zerkms

TDD infected
Команда форума
aleksei5698
А foo и foo2 куда выносить? Чем они лучше test?
 

aleksei5698

Новичок
test - конкретный экземпляр объекта
а foo и foo2 это получается свойства, в которых должны храниться экземпляры класса Foo,
а вот какие это конкретно экземпляры указывается в конфигурационном файле
PHP:
'foo' => 'test'
'foo2' => 'test2'
если власть поменяется достаточно подправить конфиг файл )
 

aleksei5698

Новичок
и еще, допустим класс загрузил конфигурацию $config[]
вот kohana кое где делает так

PHP:
class Some{
  public $config;
  public function doCalc(
    return config['x'] + config['y'] + config['z'];
  )
}
считаю это неправильным, думаю всегда надо так:

PHP:
class Some{
  public $x;
  public $y;
  public $z
  public function doCalc(
    return $this->x + $this->y + $this->z;
  )
  public function loadConfig{
    $this->x = config['x'];
    $this->y = config['y'];
    <...>
    // если свойств 3 еще куда не шло, а если их 20? тупой маппинг какой то получается
  }
}
 

Ragazzo

TDD interested
aleksei5698
PHP:
>>// если свойств 3 еще куда не шло, а если их 20? тупой маппинг какой то получается
foreach($this->config as $k=>$v)
    $this->$k = $v;
???
 

fixxxer

К.О.
Партнер клуба
Да нормально, смесь фабрики с lazy initialization и регистри.

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

Похожее использую в небольших проектах (пример - но фабрики тут как таковой нет, конечно).

Для крупных DI удобнее.
 

Здыхлик

Kohaner
Команда форума
А почему не сделать драйвер FB для родного Kohan'овского Database? Прикрутить к нему транзакции и вперед.
 

zerkms

TDD infected
Команда форума
Здыхлик
Какие ещё транзакции в FB Graph API?

Да и смысла особого нету, потому как fb sdk вполне себе и без дополнительного оборачивания отличный.
 
Сверху