Создание «фабрики» на PHP - PullRequest
       2

Создание «фабрики» на PHP

0 голосов
/ 05 февраля 2011

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

    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, и я знаю, что есть некоторые новые функции, которые могут быть полезны длясоздание "фабрики" (поздние статические привязки?).Мои знания ООП довольно легки, поэтому мне интересно, есть ли у некоторых структурные предложения, чтобы создать уникальный класс, который будет вызывать правильный конструктор.

Спасибо!

Ответы [ 2 ]

5 голосов
/ 05 февраля 2011

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

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));
}

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

Также, если это часть проекта, вы можете отделить слой View (ваш HTML-вывод) от этого слоя Model, т.е. реализовать MVC ...

1 голос
/ 05 февраля 2011

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

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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...