LoginSignup
0
1

More than 5 years have passed since last update.

【PHPデザインパターン】23_Visitor~要素と要素に対する操作を分離する

Posted at

引用記事

この記事を書くきっかけになったブログです。

記事内の解説やソースコードは、こちらのブログと著者の公開リポジトリを参考にしています。

Do You PHP はてな〜[doyouphp][phpdp]PHPによるデザインパターン入門 - Visitor~要素と要素に対する操作を分離する

概要

  • 「visitor」は「訪問者」という意味。
  • データ構造上の要素とそれに対する操作を分離する。
  • データ構造から分離された「操作」がデータ構造を渡り歩き、順に処理を行っていく。

構成要素

Visitorクラス

  • 操作のクラス階層で最上位に位置するクラス。

ConcreteVisitorクラス

  • Visitorクラスのサブクラス。

Elementクラス

  • データ構造のクラス階層で最上位に位置するクラス。
  • Visitor型のオブジェクトを受け入れるためのメソッドを宣言する。

ConcreteElementクラス

  • Elementクラスのサブクラス。

ObjectStructureクラス

  • Elementクラスの集合を表すクラス。

実演

処理の流れ

  • ItemObjArray型オブジェクトをデータ構造とする。プロパティとして、stdClass型オブジェクトを要素とする配列を保持している。
  • ItemObjArrayクラスでVistor型オブジェクトを受け入れるメソッドを用意する。
  • DumpVisitorクラスから各要素のプロパティを出力する。
  • CountVisitorクラスから要素数を出力する。
  • 今回はConcreteElementクラスを作成していない。

ファイル構造

MyVisitor
  ├── CountVisitor.php
  ├── DumpVisitor.php
  ├── ItemObjArray.php
  ├── Visitor.php
  └── my_client.php

ソースコード

Visitorクラス

Visitor.php

Visitor.php
<?php
namespace DoYouPhp\PhpDesignPattern\Visitor\MyVisitor;

use DoYouPhp\PhpDesignPattern\Visitor\MyVisitor\ItemObjArray;

/**
 * Visitorクラスに相当する
 */
interface Visitor
{
    public function visit(ItemObjArray $item_obj_array);
}

ConcreteVisitorクラス

DumpVisitor.php

DumpVisitor.php
<?php
namespace DoYouPhp\PhpDesignPattern\Visitor\MyVisitor;

use DoYouPhp\PhpDesignPattern\Visitor\MyVisitor\Visitor;
use DoYouPhp\PhpDesignPattern\Visitor\MyVisitor\ItemObjArray;

/**
 * ConcreteVisitorクラスに相当する
 */
class DumpVisitor implements Visitor
{
    // ItemObjArray型オブジェクトで保持しているstdClass型オブジェクトのプロパティを返す
    public function visit(ItemObjArray $item_obj_array)
    {
      foreach ($item_obj_array->getObjArray() as $obj) {
          echo $obj->item_name.'<br>'."\n";
      }
    }
}

CountVisitor.php

CountVisitor.php
<?php
namespace DoYouPhp\PhpDesignPattern\Visitor\MyVisitor;

use DoYouPhp\PhpDesignPattern\Visitor\MyVisitor\Visitor;
use DoYouPhp\PhpDesignPattern\Visitor\MyVisitor\ItemObjArray;

/**
 * ConcreteVisitorクラスに相当する
 */
class CountVisitor implements Visitor
{
    // ItemObjArray型オブジェクトで保持しているstdClass型オブジェクトの数を返す
    public function visit(ItemObjArray $item_obj_array)
    {
        echo count($item_obj_array->getObjArray());
    }
}

Elementクラス

兼ObjectStructureクラス。

ItemObjArray.php

ItemObjArray.php
<?php
namespace DoYouPhp\PhpDesignPattern\Visitor\MyVisitor;

use DoYouPhp\PhpDesignPattern\Visitor\MyVisitor\Visitor;

/**
 * Elementクラス兼ObjectStructureクラスに相当する
 * Visitor型のオブジェクトを受け入れるためのメソッドを宣言する
 */
class ItemObjArray
{
    private $item_obj_array;

    // 配列の要素をstdClass型オブジェクト化して、配列型プロパティに加える
    public function __construct($item_array)
    { 
        $item_obj_array = array();

        foreach($item_array as $item_name) {
            $obj = new \stdClass();
            $obj->item_name = $item_name;

            $this->item_obj_array[] = $obj;
        }
    }

    // 配列型プロパティを返す
    public function getObjArray()
    {
        return $this->item_obj_array;
    }

    // Visitor型のオブジェクトを受け入れるためのメソッド
    public function accept(Visitor $visitor)
    {
        $visitor->visit($this);
    }
}

Client

my_client.php

my_client.php
<?php
namespace DoYouPhp\PhpDesignPattern\Visitor\MyVisitor;

require dirname(dirname(__DIR__)).'/vendor/autoload.php';

use DoYouPhp\PhpDesignPattern\Visitor\MyVisitor\DumpVisitor;
use DoYouPhp\PhpDesignPattern\Visitor\MyVisitor\CountVisitor;

    // ItemObjArray型オブジェクトを生成する
    $item_array = array('apple', 'orange', 'peach');
    $item_obj_array = new ItemObjArray($item_array);

    // ItemObjArray型オブジェクトで保持しているstdClass型オブジェクトのプロパティを返す
    $item_obj_array->accept(new DumpVisitor());

    // 同じインスタンスに対して別のVisitorを使用する
    // ItemObjArray型オブジェクトで保持しているstdClass型オブジェクトの数を返す
    $visitor = new CountVisitor();
    $item_obj_array->accept($visitor);
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1