1

概念:

访问者模式实际上是让外部类能够获取树形结构的每个节点的对象,对每个对象进行操作的模式, 他能让我们在不改动原有树形结构的基础上扩展功能。比如统计等等

在这种模式下,必须有的几个要素:
1: 具体的元素对象, 访问者实际要访问的位置(即节点)
2: 稳定的树形结构, 每个节点都是一个元素对象, 一般在组合模式下比较多, 他提供了让访问者能够进行访问的实际位置(即访问者访问的是具体的树形结构的某个节点的实例化对象):
3: 访问者接口,这里定义了访问者的接口方法 , 这是个在每个节点都会用到的方法,用以节点处引用访问者,从而使得访问者能够访问当前节点
4: 访问者的具体实现. 继承了访问者接口,以实现接口方法
(还可以加一个要素: 元素的接口,对应 要点1)

情景:

要给不同用户组的用户添加不同的积分。

实现:

//定义元素接口
abstract class User
{
    public function getPoint()
    {
        return rand();  //该数据应该由数据库中读取,这里就直接模拟某个值了
    }

    //这里的accept方法用于把访问者引入,在这个方法里,($visitor)访问者可以通过User类获取需要的数据进而进行相应的操作
    abstract function accept(UserVisitor $vitor);

}

//实现元素接口
class VipUser extends User
{
    //这里的getPoint()具体实现就由接口中实现了

    //在这里就把当前对象传递给了visitor 访问者, 在访问者类的visitVip方法中就能根据$this获取必要的数据进行相应的操作
    public function accept(UserVisitor $vitor)
    {
        $vitor->visitVip($this);
    }
}

class NormalUser extends User
{
    //同上的getPoint()具体实现就由接口中实现了

   //同VipUser类中的accept
    public function accept(UserVisitor $vitor)
    {
        $vitor->visitNormal($this);
    }
}

//定义访问者接口
abstract class UserVisitor
{
    //访问者必须要实现的访问不同用户的接口方法
    abstract function visitVip(User $user);
    abstract function visitNormal(User $user);
}

//积分操作的访问者实现
class PointActVisitor extends UserVisitor
{
    public function visitVip(User $user)
    {
        echo 'Vip用户+10分 </br>';
    }

    public function visitNormal(User $user)
    {
        echo 'Normal用户+5分</br>';
    }
}

//用户的树形结构
class Users
{
    protected $users;
    public function addUser(User $user)
    {
        $this->users[] = $user;
    }

    //让所有的用户都能被访问者访问
    public function handleVisitor(UserVisitor  $visitor)
    {
        foreach($this->users as $user)
        {
            $user->accept($visitor);
        }
    }
}

$pointVisitor = new PointActVisitor();

$users = new Users();
$users->addUser(new VipUser());  //添加新用户
$users->addUser(new NormalUser());
$users->addUser(new NormalUser());

$users->handleVisitor($pointVisitor); //执行PointActVisitor访问者的操作

结果:

Vip用户+10分 
Normal用户+5分
Normal用户+5分

Yi_Zhi_Yu
1.9k 声望69 粉丝

PHPer,Sphinxer,Giter,Sheller,Pythoner