Если вы хотите создать пакетную функцию, используйте 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 для создания команд проверки.
Для имен методов не требуется execute
и undo
. Назовите его check
, если хотите. Оставьте undo
, если вам это не нужно. Основная идея по-прежнему остается прежней: один интерфейс для всех команд, которые будут командовать, что бы это ни казалось. Не стесняйтесь адаптироваться.
Альтернатива с несколько иной UseCase - это шаблон Chain of Reponsibility. Проверьте это, чтобы убедиться, что это тоже полезно.
Благодарим вас за ответ. Что-то я не совсем понимаю; вы пишете * Один класс, реализующий интерфейс, будет командиром *, а затем запустите код с помощью * public function BatchCommander реализует BatchCommand * Это опечатка или я не понимаю принцип? – MattW
@ Matt это специально. BatchCommander управляет всеми BatchCommands, но это также сама команда. Это позволяет создать произвольную древовидную структуру, сгруппировав BatchCommands в BatchCommander. Я буду обновлять сообщение для примера. – Gordon
Еще раз спасибо Гордон, я ценю ваше время и дополнения. Я действительно пропустил точку (группировку и укладку), которую я сейчас понимаю (и я в восторге от этого :)) Однако я до сих пор не понимаю, где _invoke_ _public function batchCommander_ К моему (действительно ограниченному) знание это метод, который должен находиться в классе, но какой класс? Если я использую ваш пример, я получаю * Ошибка синтаксиса: ошибка синтаксиса, непредвиденная ошибка T_PUBLIC * относительно строки _public function_ nr. – MattW