我的测试应用程序的PHP设计(模式?)是什么?

时间:2010-03-02 08:32:49

标签: php interface frameworks design-patterns factory

我想编写一个简单类(PHP5),可以“运行”未知数量的子类。这些子类最好翻译为“检查”;他们都会或多或少地做同样的事情并给出答案(真/假)。将其视为系统启动检查。

随着时间的推移,新的检查(子类)将被添加到目录中,并且在调用主类时它们应该自动运行。其他人可能会写支票,但他们必须遵循主要班级规定的职能。

构建此内容的简洁方法是什么? 我发现工厂模式并结合界面似乎是一个很好的起点。但是我不确定,我会很感激这方面的建议。

编辑:这里提供的答案都是有效的,但戈登的回答给出了批量和堆叠的其他可能性,这是我在询问时没有想到的,但现在我很高兴。

3 个答案:

答案 0 :(得分:3)

如果要创建类似批处理的功能,请使用Command Pattern

下面是一个非常简单的模式实现。我们的想法是为您要调用的所有类创建一个统一的接口。每个类封装批处理中的一个操作:

interface BatchCommand
{
    public function execute();
    public function undo();
}

实现接口的一个类将是所有子类的指挥官:

class BatchCommander implements BatchCommand
{
    protected $commands;

    public function add(BatchCommand $command)
    {
        $this->commands[] = $command;
    }
    public function execute()
    {
        foreach($this->commands as $command) {
            $command->execute();
        }
    }
    public function undo()
    {
        foreach($this->commands as $command) {
            $command->undo();
        }
    }
}

一个简单的命令可能如下所示:

class FileRename implements BatchCommand
{
    protected $src;
    protected $dest;

    public function __construct($src, $dest)
    {
        $this->$src;
        $this->dest;
    }

    public function execute()
    {
        rename($this->src, $this->dest);
    }

    public function undo()
    {
        rename($this->dest, $this->src);
    }
}

然后您可以像这样使用它:

$commander = new BatchCommander;
$commander->add(new FileRename('foo.txt', 'bar.txt'));
$commander->add(/* other commands */);
$commander->execute();

由于BatchCommander本身就是BatchCommand,因此您可以轻松地将属于一起的批次堆叠到其他批次中,从而创建一个非常灵活的树结构,例如

$batch1 = new BatchCommander;
$batch1->add(/* some command */);
$batch1->add(/* some other command */);

$batch2 = new BatchCommander;
$batch2->add(/* some command */);
$batch2->add(/* some other command */);

$main = new BatchCommander;
$main->add($batch1);
$main->add($batch2);
$main->execute();

在您的检查/测试环境中,这意味着您可以将概念上属于的单个测试分组到测试套件中。您可以通过将一个套件堆叠到另一个套件中来创建测试套件的测试套件。

当然,您还可以为BatchCommander提供一个文件路径来检查实例化,并通过运行文件路径中的文件使其初始化所有BatchCommands。或者传递一个Factory实例来用于创建Check命令。

您不必拥有方法名称executeundo。如果需要,将其命名为check。如果您不需要,请忽略undo。虽然基本思想仍然保持不变:所有类的一个接口都可以被命令,无论看起来如何。随意适应。

具有稍微不同的UseCase的替代方案是Chain of Reponsibility模式。看看它是否也有用。

答案 1 :(得分:1)

我想这里的问题是你如何找到应该实例化和运行的类,因为你需要知道类的名称。

我建议您在目录中加载每个* .php文件并使用简单的命名约定。例如,文件名(减去扩展名)是类的名称。然后就是:

 // foreach $file in glob("*.php"):
    $classname = basename($file, ".php");
    $instance = new $classname(); 
    $result = $instance->runCheck();

其中runCheck()是每个类必须提供的实际方法。

您没有说任何关于以任何特定顺序运行检查的内容,但可以通过向每个文件添加nn_前缀并按顺序加载它们来解决这个问题。例如05_CheckFoo.php

答案 2 :(得分:0)

检查类自动加载,因此您不必考虑存在多少个子类。 PHP将采取一切: http://php.net/manual/en/language.oop5.autoload.php