Построение «фабрики» в PHP

Я создал класс File, который выполняет все операции с файлами, I / O и действует по-разному в зависимости от характера файлов. Я не доволен своей фактической структурой, которая выглядит так:

class File { function __construct($id) { $bbnq = sprintf(" SELECT * FROM documents WHERE id = %u", $id); $req = bbnf_query($bbnq); $bbn = $req->fetch(); $this->file_type = $bbn['file_type']; $this->file_name = $bbn['file_name']; $this->title = $bbn['title']; } function display() { return '<a href="'.$this->file_name.'">'.$this->title.'</a>'; } } class Image extends File { function __construct($id) { global $bbng_imagick; if ( $bbng_imagick ) $this->imagick = true; parent::__construct($id); } function display() { return '<img src="'.$this->file_name.'" alt="'.$this->title.'" />'; } } 

Здесь мне нужно сначала узнать тип файла, чтобы определить, какой класс / подкласс использовать.
И я хотел бы получить обратное, то есть отправить идентификатор в мой класс, который возвращает объект, соответствующий типу файла.
Я недавно обновился до PHP 5.3, и я знаю, что есть некоторые новые функции, которые могут быть полезны для создания «фабрики» (поздние статические привязки?). Мои знания ООП довольно легкие, поэтому я задаюсь вопросом, есть ли у некоторых конструктивные предложения, чтобы создать уникальный класс, который будет называться правильным конструктором.

Благодаря!

Я не думаю, что поздние статические привязки здесь актуальны – заводская модель их не требует. Попробуй это:

 class FileFactory { protected static function determineFileType($id) { // Replace these with your real file logic $isImage = ($id>0 && $id%2); $isFile = ($id>0 && !($id%2)); if ($isImage) return "Image"; elseif ($isFile) return "File"; throw new Exception("Unknown file type for #$id"); } public static function getFile($id) { $class = self::determineFileType($id); return new $class($id); } } // Examples usage(s) for ($i=3; $i>=0; $i--) { print_r(FileFactory::getFile($i)); } 

В стороне, вы обязательно должны избегать выхода из БД, независимо от того, насколько безопасным вы это считаете. Тест с двойными кавычками в заголовке, например (не говоря уже о более вредоносных вводах).

Кроме того, если это часть проекта, вам может потребоваться отделить слой «Вид» (ваш вывод HTML) от этого уровня модели, то есть реализовать MVC …

В конструкторе фабрики вам необходимо определить тип файла, а затем создать объект соответствующего класса. Что-то вроде этого возможно:

 class File { public static function factory($id) { $fileData = <query this $id> switch ($fileData->type) { case image: return new ImageFile($fileData); break; case html: return new HtmlFile($fileData); break; default: // error? } } } abstract class FileAbstract { // common file methods here } // override the custom bits for each type class ImageFile extends FileAbstract { public function display() { // ... } } class HtmlFile extends FileAbstract { public function display() { // ... } } 

Тогда ваш код будет просто:

 $myFile = File::factory($id); $myFile->display();