Menu
Coddy logo textTech

Commandパターン

CoddyのPHPジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 75/91。

Command パターンは、リクエストに関するすべての情報を含む独立したオブジェクトにリクエストを変換する振る舞いに関するデザインパターンです。この変換により、リクエストをメソッドの引数として渡したり、リクエストの実行を遅延またはキューに入れたり、取り消し可能な操作をサポートしたりできます。

レストランを思い浮かべてみてください。

食べ物を注文すると、ウェイターは注文を伝票(command)に書き、それを厨房へ持って行き、シェフが実行します。ウェイターは料理の仕方を知る必要はなく、commandを届けるだけです。

これにより、要求者と実行者が分離されます。

基本的な実装は次のとおりです:

<?php
interface Command {
    public function execute(): string;
}
class Light {
    public function on(): string { return "Light is ON"; }
    public function off(): string { return "Light is OFF"; }
}
class LightOnCommand implements Command {
    public function __construct(private Light $light) {}
    
    public function execute(): string {
        return $this->light->on();
    }
}
class LightOffCommand implements Command {
    public function __construct(private Light $light) {}
    
    public function execute(): string {
        return $this->light->off();
    }
}

invoker は、commands が何をするのかを知らずに commands を起動します:

<?php
class RemoteControl {
    public function press(Command $command): string {
        return $command->execute();
    }
}
$light = new Light();
$remote = new RemoteControl();

echo $remote->press(new LightOnCommand($light)) . "\n";
echo $remote->press(new LightOffCommand($light));

出力:

Light is ON
Light is OFF

Command Patternは、操作をキューに追加したり、取り消し機能をImplementしたり、アクションをログに記録したりする必要がある場合に特に優れています。各commandは自己完結しているため、既存のコードを変更せずに新しいcommandsを簡単に追加できます。

challenge icon

チャレンジ

簡単

Command パターンを使用して、テキストエディターの command システムを構築しましょう。テキストエディターでは、テキストの書き込み、テキストの削除、アクションの取り消しなどの操作をサポートする必要があることがよくあります。それぞれの操作を自己完結型の command オブジェクトにし、統一された interface を通じて実行できるようにします。

コードを4つのファイルに分けて整理します。

  • Command.php:単一のメソッド execute(): string を持つ Command interface を Define します。これにより、すべてのエディター command が従うべき contract が確立されます。
  • TextEditor.php:receiver、つまり実際に処理を実行するオブジェクトを表す TextEditor class を Create します。エディターには次の機能を持たせます。
    • current のテキスト content を保存する(empty 文字列から開始)
    • テキストを content に追加し、"Written: [text]" を返す write(string $text): string メソッドを持つ
    • content を空にし、"Content cleared" を返す clear(): string メソッドを持つ
    • current の content を返す getContent(): string メソッドを持つ
  • Commands.php:Command ファイルと TextEditor ファイルを Include します。Command interface を Implement する2つの command class を Create します。
    • WriteCommand:constructor で TextEditor とテキスト文字列を受け取ります。その execute() メソッドはエディターの write() メソッドを calls し、その結果を返します。
    • ClearCommand:constructor で TextEditor を受け取ります。その execute() メソッドはエディターの clear() メソッドを calls し、その結果を返します。
  • main.php:Commands ファイルを Include します。2つの入力を受け取ります。command type("write" または "clear")と、テキスト文字列(write command の場合のみ使用)です。

    TextEditor instance を Create します。command type Based で、appropriate な command オブジェクトを Create します。次に、command に対して execute() を calls し、結果を出力する invoker function または単純な仕組みを Create します。

    新しい行に、エディターの current の content を次の format で出力します:Content: [content](empty の場合は、スペースの後に何も付けず Content: とだけ出力します)。

この challenge は、Command パターンが各操作をオブジェクトとしてカプセル化する方法を示します。invoker は、write command を実行しているのか clear command を実行しているのかを知る必要がありません。単に execute() を calls し、詳細の処理を command に任せます。

REQUIRED OUTPUT FORMAT: [翻訳したコンテンツ]

自分で試してみよう

<?php

require_once 'Commands.php';

// 入力を読み取る
$commandType = trim(fgets(STDIN)); // "write" または "clear"
$text = trim(fgets(STDIN));         // writeコマンド用のテキスト

// TODO: TextEditorインスタンスを作成する

// TODO: コマンドタイプに基づいて、適切なコマンドオブジェクトを作成する
// - "write"の場合、エディタとテキストでWriteCommandを作成する
// - "clear"の場合、エディタでClearCommandを作成する

// TODO: コマンドのexecute()を呼び出すインボーカー機構を作成する
// そして結果を出力する

// TODO: エディタの現在のコンテンツを次の形式で出力する: "Content: [content]"
// (空の場合は、スペースの後に何も付けずに "Content: " とだけ出力する)

?>
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: PHPオンラインコンパイラ