Лоадер для двух классов

Лоадер для двух классов

Существуют два класса, объекты которых хранят в себе некоторые данные. Для того чтоб абстрагироваться от источника данных (БД, ini файл, xml файл etc), для загрузки данных в объекты используются так называемые лоадры (Loaders). Т.е. (псевдокод):
PHP:
a = A->new(...);
b = B->new(...);

loaderA->load(a);
loaderB->load(b);
Возникла следующая ситуация: данные для обоих классов хранятся в одном xml конфигурационном файле и парсить его два раза в каждом из лоадеров нет никакого желания. В голову пришло два решения.

1. Общий лоадер для A и B:
PHP:
loader = Loader->new(config.xml);
loader->load(a, b);
или
PHP:
loader = Loader->new(config.xml);
loader->loadA(a);
loader->loadB(b);
Просто, но как-то некрасиво.

2. Некий вспомогательный класс-менеджер:
PHP:
cm = ConfigManager->new(config.xml); // в конструкторе загрузка и парсинг конфига
loaderA = LoaderA->new(cm);
loaderB = LoaderB->new(cm);
...
loaderA->load(a);
loaderB->load(b);
Вроде бы логично, однако имеет место оверхед в ConfigManager. Ведь конфигурационный файл нужно парсить на этапе создания объекта(иначе ConfigManager не имеет никакого смысла) и хранить данные в самом объекте до того, пока их не запросит лодер.

Больше ничего придумать не могу. Посоветуйте, пожалуйста, какое-нибудь элегантное решение.

Постскриптум. Если ошибся форумом - перенесите, пожалуйста, в нужный.
 

ForJest

- свежая кровь
Чёт я так и не понял в чём собственно проблема.
Если нужно парсить один раз - сделай "кэширующий" класс, который будет парсить XML и к которому будут обращаться уже LoaderA и LoaderB.
 

SiMM

Новичок
Для PHP4
PHP:
class Loader{
  function Load($file){
    static $list = array();
    if (isset($list[$file])) return $list[$file];
    else return $list[$file] = "результат парсинга $file\n";
  }
}
PS: рассматривать только как идею

-~{}~ 23.09.05 23:30:

PPS: походу мне срочно надо спать :)
 
Автор оригинала: ForJest
Чёт я так и не понял в чём собственно проблема.
Если нужно парсить один раз - сделай "кэширующий" класс, который будет парсить XML и к которому будут обращаться уже LoaderA и LoaderB.
Если вчитаться в мое сообщение, то второй вариант - это как раз то, о чем ты пишешь ;=) Что меня смущает я уже написал.
 

ForJest

- свежая кровь
2NetFly
Я не понял всё равно в чём проблема. Если нужно парсить один раз - парси один раз и всё.
 
В описываемом мной примере парсинг происходит единожды при создании ConfigManager (это и есть "кэширующий" класс"). Затем лоадеры обращаются к cm за данными. Однако отпарсенные данные нужно как-то хранить до прихода лоадеров, и их (данных) структура повторяет то, что реализовано в конечных классах A и B. Вот это мне и не нравится. Надеюсь, у меня получилось объяснить.
 

svetasmirnova

маленький монстрик
Можно "частями" парсить, соответственно не хранить. Идея, правда, от этого не меняется.
 

ForJest

- свежая кровь
2NetFly
и их (данных) структура повторяет то, что реализовано в конечных классах A и B
Чёт я тогда вообще не пойму. Если после парсинга XML получаются по сути объекты класса A и B - то может быть сделать
PHP:
$a = &$cm-> get_a();
$b = &$cm-> get_b();
Ну или если по простому - то во время парсинга создаётся набор объектов подходящего типа. И потом мы просто их получаем. Если нету - не получаем.
 

Screjet

Новичок
Если источник для А и Б один, то передавай его этим объектам, типа
PHP:
loader = new xml_loader(config.xml);
A = new A( loader, ... );
B = new B( loader, ... );
 

whirlwind

TDD infected, paranoid
я бы сделал так
PHP:
$cm = new ClassManager('config.xml');
$a = $cm->MakeInstance('a');
$b = $cm->MakeInstance('b');
ЗЫ. или правда, "статический" атрибут класса, а класс унаследовать
 
Автор оригинала: ForJest
2NetFly

Чёт я тогда вообще не пойму. Если после парсинга XML получаются по сути объекты класса A и B - то может быть сделать
PHP:
$a = &$cm-> get_a();
$b = &$cm-> get_b();
Автор оригинала: whirlwind
я бы сделал так
PHP:
$cm = new ClassManager('config.xml');
$a = $cm->MakeInstance('a');
$b = $cm->MakeInstance('b');
Фактически то же самое, что я описал в первом решении первого сообщения. Только фабрика в данном случае менее гибкая т.к. если возникнет необходимость заместить какой-то из объектов A и B нужно будет переопределить ClassManager.
 

Screjet

Новичок
Еще, как вариант, сделать из лодера регистр, типа:
PHP:
class xml_loader {

  static $register = array();

  function instance( $file ){
    if ( !isset(self::$register[$file]) ){
      return self::$register[$file] = new self($file);
    } else {
      return self::$register[$file];
    }
  }

  private function __construct( $file ){
    //..
  }
}

$A = new A( xml_loader::instance("file.xml") );
$B = new B( xml_loader::instance("file.xml") );
 

ForJest

- свежая кровь
2NetFly
Фактически ты получил здесь помощь, о которой просил.
Если ты написал в первом решении первого сообщения - то зачем весь этот цирк?
 
Автор оригинала: ForJest
2NetFly
Фактически ты получил здесь помощь, о которой просил.
Если ты написал в первом решении первого сообщения - то зачем весь этот цирк?
Я просил "какое-нибудь элегантное решение" (возможно, забыл слово "другое"?), а получил вариации не тему двух решений, описанных в первом сообщении, которые по условию задачи меня не устраивали.

Я благодарен за попытки помочь, но так же очень прошу не уходить далеко от темы топика.

Чем меня не устраивает фабрика я уже написал: создание классов "вшито" в CM и при переопределении A или B придется наследовать CM и переопределять методы MakeInstance.
 

ForJest

- свежая кровь
2NetFly
Однако отпарсенные данные нужно как-то хранить до прихода лоадеров, и их (данных) структура повторяет то, что реализовано в конечных классах A и B. Вот это мне и не нравится.
Чем меня не устраивает фабрика я уже написал: создание классов "вшито" в CM и при переопределении A или B придется наследовать CM и переопределять методы MakeInstance.
Это начинает уже походить на слова капризного ребёнка :). Все эти "нравится", "элегантно", "как-то некрасиво" - это дилетанство.
Твои критерии "элегантности" очень мутные получаются. Равно как и "нравится".

Если тебе нужно парсить один раз - то парси один раз и храни в кэше - по-моему тривиальное решение. А ты начинаешь про "внутреннее представление" что-то рассказывать.
Если ты знаешь как тебе нравится - возьми и сделай, блин.
-----------------------------
Ещё раз. В результате парсинга получается что? Данные, соотвествуещие двум экземлярам объектов. Распарсил - сохрани их где-нибудь. Это кэш готовых объектов, которые получились в результате парсинга - тебе же именно это нужно? Распарсить один раз и получить данные для нескольких объектов?
Дальше тебе ничего посоветовать просто нельзя, т.к. тебя не устраивает "внутренняя структура", о которой никто ничего не знает. Поэтому либо ты раскрываешь с чем у тебя проблемы, либо не морочишь дальше голову, а думаешь сам.
--------------------------------
- Доктор у меня болит.
- Где болит?
- Да везде! Куда ни ткну - везде болит!
- Да у вас же палец сломан...
Как раз из этой серии :).
--------------------------------
Либо ты начинаешь излагать как специалист - в технических терминах, либо не нужно дальше разводить флуд, пожалуйста.
 

ForJest

- свежая кровь
svetasmirnova
По-моему человек просто не в состоянии абстрагироваться от своего XML.
PHP:
$Data=array(
array(
'class'=> 'A'
'data'=> array(...)
),
array(
'class'=> 'B'
'data'=> array(...)
),
...
array(
'class'=> 'Z'
'data'=> array(...)
),
);
Я бы уже пока он тут выдумывает "Элегантное решение" написал бы враппер вокруг данных из массива data с методами доступа.
по типу
PHP:
function get_field()
{
return $this-> data['field'];
}
Или сделал бы в каждом классе
set_data, для инциализации значений.
PHP:
function set_data($data)
{
$this-> set_field($data['field']);
$this-> set_field2($data['field2']);
}
-----------------------
А человек не в состоянии определится даже с клиентской частью вызовов и оперирует "нравится не нравится" - это дилетантский подход.
К тому же да, я признаю что прощёлкал с самого начала преждевременную оптимизацию. И теперь человек, чтобы 2 раза не парсить какой-то XML второй день ищет "элегантное решение".
 

Screjet

Новичок
svetasmirnova
У него в проектировании какаято каша. Любое решение = это костыль.
Какой глубокий смысл двум разным объектам использовать один конфиг?
Либо объекты не верно спроектированы, либо конфиг из разряда "засунем в него все что можно".
 
Первые два абзаца комментировать не буду, ибо не хочу ввязываться в бессмысленную полемику. А вот касательно:
Ещё раз. В результате парсинга получается что? Данные, соотвествуещие двум экземлярам объектов. Распарсил - сохрани их где-нибудь. Это кэш готовых объектов, которые получились в результате парсинга - тебе же именно это нужно? Распарсить один раз и получить данные для нескольких объектов?
Тут все верно. Я из-за невнимательности неверно интерпретировал преведенный тобой код:
PHP:
$a = &$cm-> get_a();
$b = &$cm-> get_b();
и подумал, что создание a и b происходит во время вызова get_a и get_b (т.е. cm представляет собой обычную фабрику), а не в конструкторе cm, как ты имел в виду. Теперь все ясно.

Я немного позже опишу все проблему.

-~{}~ 25.09.05 17:08:

Screjet
Как ты можешь судить о том, целесообразно ли хранить данные в одном файле или нет, если ты не имеешь никакого предоставления ни о системе ни о конфиге? То же самое касается громких фраз о "каше" и об "ошибках проектирования".

ForJest
Я все понимаю, но зачем продолжать меня лечить, если ты сам выше написал, что не зная деталей проблемы посоветовать больше нечего?

По-моему человек просто не в состоянии абстрагироваться от своего XML.
Я абстрагировался от источника данных на начальном этапе (когда xml конфигом и не пахло), для этого и были использованы лоадеры:
PHP:
c = C->new(loaderA, loaderB);
...
process
{
	a = A->new(...); // параметры присутсвуют
	loaderA->load(a);
	b = B->new(...);
	loaderB->load(b);
	...
}
Предполагалось, что лоадеры будет получать данные из разных источников. Однако позже возникла необходимость получать данные из одного источника. Я второй день произвожу парсинг конфига в каждом из лоадеров, что не мешает мне продолжать искать другое решение, которое позволит мне парсить конфиг один раз и не заставит менять дизайн системы, в частности реализацию класса C.

Постскриптум: я слово "нравится" употребил один раз, там, где оно было нужно. Ты же его повторяешь в каждом сообщении, может хватит?
 
Сверху