@blog.justoneplanet.info

日々勉強

Interpreter Pattern

言語の文法

<Job> ::= begin <CommandList>
<CommandList> ::= <Command>* end
<Command> ::= diskspace | date | line
interface Command {
    public function execute(Context $context);
}

JobCommand.php

<Job> ::= begin <CommandList>
class JobCommand implements Command {
    public function execute(Context $context) {
        if($context->getCurrentCommand() !== 'begin') {
            throw new RuntimeException();
        }
        $commandList = new CommandListCommand();
        $commandList->execute($context->next);
    }
}

CommandListCommand.php

<CommandList> ::= <Command>* end
class CommandListCommand implements Command {
    public function execute(Context $context) {
        while(true) {
            $currentCommand = $context->getCurrentCommand();
            if(is_null($currentCommand)) {
                throw new RuntimeException();
            }
            else if($currentCommand === 'end') {
                break;
            }
            else {
                $command = new CommandCommand();
                $command->execute($context);
            }
        }
        $context->next();
    }
}

CommandCommand.php

<Command> ::= diskspace | date | line
class CommandCommand implements Command {
    public function execute(Context $context) {
        $currentCommand = $context->getCurrentCommand();
        if($currentCommand === 'diskspace') {
            // 空き容量を計算して出力
        }
        else if($currentCommand === 'date') {
            // 日付出力
        }
        else if($currentCommand === 'line') {
            // 罫線を出力
        }
        else {
            new RuntimeException();
        }
    }
}

Context.php

class Context {
    private $commands;
    private $currentIndex = 0;
    private $maxIndex = 0;
    public function __construct($command) {
        $this->commands = split(' +', trim($command));
        $this->maxIndex = count($this->commands);
    }
    public function next() {
        $this->currentIndex++;
        return $this;        
    }
    public function getCurrentCommand() {
        if(!array_key_exists($this->currentIndex, $this->commands)) {
            return null;
        }
        return trim($this->commands[$this->currentIndex]);
    }
}

■クライアントコード

$job = new JobCommand();
$job->execute(new Context('begin date line diskspace end'));

コメントはまだありません»

No comments yet.

RSS feed for comments on this post.TrackBack URL

Leave a comment