Я ищу хороший способ реализации шаблона Adapter со статическими классами в PHP 5.x.
Один из примеров, где я хотел бы использовать это, является аналогом Python os.path.join()
.
У меня будет два адаптера: класс адаптера для Windows и Linux.
Я считаю разумным реализовать эти классы как статические классы, потому что они не имеют "контекста". Им не нужно хранить какое-либо состояние, и создание экземпляра каждый раз, когда он мне нужен, кажется излишним - поэтому я ищу чистый способ реализации этого.
Давайте рассмотрим следующую фиктивную реализацию:
static public function join(){
$parts = func_get_args();
$joined = array(MY_MAGICALLY_PASSED_DEFAULT_PATH_PREFIX);
foreach($parts as $part){
$part = self::$adaptee->cleanPath($path);
if(self::$adaptee->isAbsolute($part)){
$joined = array($part);
}
else{
$joined[] = $part;
}
}
return implode(PATH_SEPARATOR, $joined);
}
Первое, что вы заметите, это то, что он предполагает инициализированный статический элемент с именем adaptee, который будет содержать необходимые, зависящие от ОС детали реализации.
Это требует, чтобы у меня была произвольно названная статическая конструкторская функция, которую я бы вызвал сразу после объявления класса. (Еще одна вещь, которая беспокоит меня с этим подходом).
Конечно, я мог бы инициализировать локальную переменную $adaptee
при каждом вызове метода, но это кажется неуместным, и мне пришлось бы повторять это в каждой статической функции, которая нуждается в адаптере.
Теперь ... для деталей реализации классов PHP: они не являются объектами первого класса, поэтому я не мог просто передать класс в качестве аргумента. В этом примере требуется, чтобы я создал Adaptees как нестатические (как это называется?) Классы, затем создал его экземпляр и в конечном итоге назначил его статической переменной-члену $adaptee
адаптера класс.
Может быть, это просто странная и совершенно субъективная мысль, которая у меня есть ... но я действительно чувствую, что неуместно делать это так. У вас есть идеи по поводу лучшей реализации?
Еще одна идея, которая у меня возникла, заключается в том, чтобы вместо этого сохранить имя класса адаптера и использовать call_user_func
вместо этого, но я не чувствую себя слишком комфортно, используя этот подход.
Обновление
Возможно, я не описал это должным образом, поэтому я попытаюсь объяснить это в обновлении:
Я не смотрю на то, как получить базовую операционную систему, но мне бы хотелось, чтобы статический класс действовал по-разному в зависимости от того, является ли ОС Linux, Windows, FreeBSD или чем-то еще.
Я думал о шаблоне адаптера, но поскольку у меня нет статического конструктора, я не могу действительно инициализировать класс. Одним из способов было бы инициализировать его в начале каждого открытого статического вызова метода (или просто проверить, инициализирован ли он).
Другой возможностью было бы создать статический конструктор-подобный метод и просто вызвать его сразу после объявления. Это могло бы сработать, но мне просто интересно, какие еще, возможно, более изящные методы существуют для достижения этой цели.
Что касается моего начального примера:
Предполагается, что это служебная функция, ей действительно не нужно сохранять состояние в каком-либо виде, поэтому я не ищу объект Path любого типа. То, что я хотел бы, это функция фабрики Path, которая возвращает строку без необходимости различать различные ОС каждый раз при вызове. «Библиотека» привела меня к созданию статического класса в качестве псевдо-пространства имен для моих связанных служебных функций и различных деталей реализации, которые необходимо поддерживать в шаблоне адаптера. Сейчас я ищу элегантный способ, чтобы объединить их.