PHP 设计模式系列 -- 访问者模式(Visitor)

php中文网
发布: 2016-06-23 13:19:09
原创
1363人浏览过

1、模式定义

我们去银行柜台办业务,一般情况下会开几个个人业务柜台的,你去其中任何一个柜台办理都是可以的。我们的访问者模式可以很好付诸在这个场景中:对于银行柜台来说,他们是不用变化的,就是说今天和明天提供个人业务的柜台是不需要有变化的。而我们作为访问者,今天来银行可能是取消费流水,明天来银行可能是去办理手机银行业务,这些是我们访问者的操作,一直是在变化的。

访问者模式就是表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

2、UML类图

百灵大模型
百灵大模型

蚂蚁集团自研的多模态AI大模型系列

百灵大模型 177
查看详情 百灵大模型

3、示例代码

RoleVisitorInterface.php

<?phpnamespace DesignPatternsBehavioralVisitor;/** * 访问者接口 */interface RoleVisitorInterface{    /**     * 访问 User 对象     *     * @param DesignPatternsBehavioralVisitorUser $role     */    public function visitUser(User $role);    /**     * 访问 Group 对象     *     * @param DesignPatternsBehavioralVisitorGroup $role     */    public function visitGroup(Group $role);}
登录后复制

RolePrintVisitor.php

<?phpnamespace DesignPatternsBehavioralVisitor;/** * Visitor接口的具体实现 */class RolePrintVisitor implements RoleVisitorInterface{    /**     * {@inheritdoc}     */    public function visitGroup(Group $role)    {        echo "Role: " . $role->getName();    }    /**     * {@inheritdoc}     */    public function visitUser(User $role)    {        echo "Role: " . $role->getName();    }}
登录后复制

Role.php

<?phpnamespace DesignPatternsBehavioralVisitor;/** * Role 类 */abstract class Role{    /**     * 该方法基于Visitor的类名判断调用Visitor的方法     *     * 如果必须调用其它方法,重写本方法即可     *     * @param DesignPatternsBehavioralVisitorRoleVisitorInterface $visitor     *     * @throws InvalidArgumentException     */    public function accept(RoleVisitorInterface $visitor)    {        $klass = get_called_class();        preg_match('#([^\\]+)$#', $klass, $extract);        $visitingMethod = 'visit' . $extract[1];        if (!method_exists(__NAMESPACE__ . 'RoleVisitorInterface', $visitingMethod)) {            throw new InvalidArgumentException("The visitor you provide cannot visit a $klass instance");        }        call_user_func(array($visitor, $visitingMethod), $this);    }}
登录后复制

User.php

<?phpnamespace DesignPatternsBehavioralVisitor;class User extends Role{    /**     * @var string     */    protected $name;    /**     * @param string $name     */    public function __construct($name)    {        $this->name = (string) $name;    }    /**     * @return string     */    public function getName()    {        return "User " . $this->name;    }}
登录后复制

Group.php

<?phpnamespace DesignPatternsBehavioralVisitor;class Group extends Role{    /**     * @var string     */    protected $name;    /**     * @param string $name     */    public function __construct($name)    {        $this->name = (string) $name;    }    /**     * @return string     */    public function getName()    {        return "Group: " . $this->name;    }}
登录后复制

4、测试代码

Tests/VisitorTest.php

<?phpnamespace DesignPatternsTestsVisitorTests;use DesignPatternsBehavioralVisitor;/** * VisitorTest 用于测试访问者模式 */class VisitorTest extends PHPUnit_Framework_TestCase{    protected $visitor;    protected function setUp()    {        $this->visitor = new VisitorRolePrintVisitor();    }    public function getRole()    {        return array(            array(new VisitorUser("Dominik"), 'Role: User Dominik'),            array(new VisitorGroup("Administrators"), 'Role: Group: Administrators')        );    }    /**     * @dataProvider getRole     */    public function testVisitSomeRole(VisitorRole $role, $expect)    {        $this->expectOutputString($expect);        $role->accept($this->visitor);    }    /**     * @expectedException InvalidArgumentException     * @expectedExceptionMessage Mock     */    public function testUnknownObject()    {        $mock = $this->getMockForAbstractClass('DesignPatternsBehavioralVisitorRole');        $mock->accept($this->visitor);    }}
登录后复制

5、总结

访问者模式适用于数据结构相对稳定的系统,它把数据结构和作用于结构之上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。在本例中,User、Group 是数据结构,而 RolePrintVisitor 是访问者(用于结构之上的操作)。

当实现访问者模式时,要将尽可能多的将对象浏览逻辑放在 Visitor 类中,而不是放在它的子类中,这样的话,ConcreteVisitor 类所访问的对象结构依赖较少,从而使维护较为容易。

立即学习PHP免费学习笔记(深入)”;

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号