用PHP构建“工厂”

时间:2011-02-05 13:09:41

标签: php oop factory-pattern

我创建了一个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.'" />';
        }
    }

这里我首先要知道文件类型,以确定使用哪个类/子类 而且我想实现相反的目的,即向我的类发送一个ID,它返回一个对应于文件类型的对象 我最近更新到PHP 5.3,我知道有一些新功能可用于创建“工厂”(后期静态绑定?)。我的OOP知识非常简单,所以我想知道是否有一些结构建议,以便创建一个独特的类,它将调用正确的构造函数。

谢谢!

2 个答案:

答案 0 :(得分:5)

我不认为后期静态绑定在这里是相关的 - 工厂模式不需要它们。试试这个:

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 :(得分:1)

在工厂的构造函数中,您需要确定文件类型,然后使用它创建相应类的对象。也许是这样的事情:

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