轻松掌握php设计模式之访问者模式


Posted in PHP onSeptember 23, 2016

访问者模式解决的问题

在我们的代码编写过程当中,经常需要对一些类似的对象添加一些的代码,我们以一个计算机对象打印组成部分为例来看下:

/**
  * 抽象基类
  */
  abstract class Unit
  {
    /**
    *获取名称
    */
    abstract public function getName();

  }

  /**
  * Cpu类
  */
  class Cpu extends Unit
  {
    public function getName()
    {
      return 'i am cpu';
    }
  }

  /**
  * 内存类
  */
  class Memory extends Unit
  {
    public function getName()
    {
      return 'i am memory';
    }
  }

  /**
  * 键盘类
  */
  class Keyboard extends Unit
  {
    public function getName()
    {
      return 'i am keyboard';
    }
  }

  /**
  * 计算机类
  */
  class Computer
  {
    protected $_items = [];

    public function add(Unit $unit)
    {
      $this->_items[] = $unit;
    }

    public function print()
    {
      // 循环打印各个组成部分
      foreach ($this->_items as $item) {
        $item->getName();
      }
    }
  }

这个时候上面的代码看上去好像很完美的样子,但是问题来了,现在我们不但需要打印组成部分,还需要保存各个组件到数据库,不仅如此,还需要打印各个组件的价格;此时如果在Unit基类中添加getPrice()和save()方法,也能实现我们想要的功能,但是这样做也存在问题,你并不知道还需要新增什么操作,如果每新增一个操作都用这样的方法来新增,我们的类会变得越来越臃肿。

访问者模式的实现

而访问者模式就是为了解决这个问题的,他把数据结构和作用于结构之上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化,我们来看下面改良过得代码:

/**
  * 抽象基类
  */
  abstract class Unit
  {
    /**
    * 获取名称
    */
    abstract public function getName();

    /**
    * 用来接受访问者对象,回调访问者的visit方法
    * 非常关键的方法
    */
    public function accept(Visitor $visitor)
    {
      $method = visit . get_class($this);
      if (method_exists($visitor, $method)) {
        $visitor->$method($this);
      }
    }
  }

  /**
  * Cpu类
  */
  class Cpu extends Unit
  {
    public function getName()
    {
      return 'i am cpu';
    }
  }

  /**
  * Memory类
  */
  class Memory extends Unit
  {
    public function getName()
    {
      return 'i am memory';
    }
  }

  /**
  * Keyboard类
  */
  class Keyboard extends Unit
  {
    public function getName()
    {
      return 'i am keyboard';
    }
  }
  
  /**
  * Keyboard类
  */
  interface Visitor
  {
    public function visitCpu(Cpu $cpu);
    public function visitMemory(Memory $memory);
    public function visitKeyboard(Keyboard $keyboard);
  }

  /**
  * 
  */
  class PrintVisitor implements Visitor
  {
    public function visitCpu(Cpu $cpu)
    {
      echo "hello, " . $cpu->getName() . "\n";
    }

    public function visitMemory(Memory $memory)
    {
      echo "hello, " . $memory->getName() . "\n";
    }

    public function visitKeyboard(Keyboard $keyboard)
    {
      echo "hello, " . $keyboard->getName() . "\n";
    }
  }

  /**
  * 
  */
  class Computer
  {
    protected $_items = [];

    public function add(Unit $unit)
    {
      $this->_items[] = $unit;
    }
    
    /**
    * 调用各个组件的accept方法
    */
    public function accept(Visitor $visitor)
    {
      foreach ($this->_items as $item) {
        $item->accept($visitor);
      }
    }
  }

  $computer = new Computer();
  $computer->add(new Cpu());
  $computer->add(new Memory());
  $computer->add(new Keyboard());

  $printVisitor = new PrintVisitor();
  $computer->print($printVisitor);

  // 以上的代码将打印出  
  hello, i am cpu
  hello, i am memory
  hello, i am keyboard

总结

经过上面的改良之后,我们要扩展就变得非常容易,如果我们需要新增保存到数据库的方法,可以在新增一个实现了Visitor的类,比如SaveVisitor,在该类中来实现保存的方法,等于我们把该类和该类中的一些操作解藕了出来,而集合了类操作的对象就是访问者。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
discuz安全提问算法
Jun 06 PHP
php5.3 废弃函数小结
May 16 PHP
php下清空字符串中的HTML标签的代码
Sep 06 PHP
php 生成自动创建文件夹并上传文件的示例代码
Mar 07 PHP
destoon之一键登录设置
Jun 21 PHP
php使用parse_url和parse_str解析URL
Feb 22 PHP
10个超级有用的PHP代码片段果断收藏
Sep 23 PHP
PHP的全局错误处理详解
Apr 25 PHP
深入理解php printf() 输出格式化的字符串
May 23 PHP
PHP简单判断iPhone、iPad、Android及PC设备的方法
Oct 11 PHP
php图片合成方法(多张图片合成一张)
Nov 25 PHP
phpstorm 配置xdebug的示例代码
Mar 31 PHP
PHP接收App端发送文件流的方法
Sep 23 #PHP
适合PHP初学者阅读的4本经典书籍
Sep 23 #PHP
php版微信开发之接收消息,自动判断及回复相应消息的方法
Sep 23 #PHP
php版微信开发Token验证失败或请求URL超时问题的解决方法
Sep 23 #PHP
php版微信公众账号第三方管理工具开发简明教程
Sep 23 #PHP
php版微信公众平台接口参数调试实现判断用户行为的方法
Sep 23 #PHP
php使用CURL模拟GET与POST向微信接口提交及获取数据的方法
Sep 23 #PHP
You might like
php Sql Server连接失败问题及解决办法
2009/08/07 PHP
php中防止恶意刷新页面的代码小结
2012/10/31 PHP
完美解决thinkphp唯一索引重复时出错的问题
2017/03/31 PHP
PHP长连接实现与使用方法详解
2018/02/11 PHP
ThinkPHP框架获取最后一次执行SQL语句及变量调试简单操作示例
2018/06/13 PHP
JavaScript 设计模式学习 Factory
2009/07/29 Javascript
jQuery获取样式中颜色值的方法
2015/01/29 Javascript
javascript背景时钟实现方法
2015/06/18 Javascript
Javascript的表单与验证-非空验证
2016/03/18 Javascript
asp.net+jquery.form实现图片异步上传的方法(附jquery.form.js下载)
2016/05/05 Javascript
js从外部获取图片的实现方法
2016/08/05 Javascript
浅谈jquery选择器 :first与:first-child的区别
2016/11/20 Javascript
Node.js Koa2使用JWT进行鉴权的方法示例
2018/08/17 Javascript
用图片替换checkbox原始样式并实现同样的功能
2018/11/15 Javascript
小程序云开发教程如何使用云函数实现点赞功能
2019/05/18 Javascript
基于ssm框架实现layui分页效果
2019/07/27 Javascript
VUEX 数据持久化,刷新后重新获取的例子
2019/11/12 Javascript
Python实现Linux的find命令实例分享
2017/06/04 Python
TensorFlow实现简单卷积神经网络
2018/05/24 Python
Python测试网络连通性示例【基于ping】
2018/08/03 Python
pycharm 实现显示project 选项卡的方法
2019/01/17 Python
python自动保存百度盘资源到百度盘中的实例代码
2019/08/26 Python
Python实现RabbitMQ6种消息模型的示例代码
2020/03/30 Python
Python基于gevent实现高并发代码实例
2020/05/15 Python
python 删除系统中的文件(按时间,大小,扩展名)
2020/11/19 Python
Melissa鞋马来西亚官方网站:MDreams马来西亚
2018/04/05 全球购物
公司部门司机岗位职责
2014/01/03 职场文书
小学生元旦广播稿
2014/02/21 职场文书
旅行社优秀创业计划书
2014/08/16 职场文书
2014物价局群众路线对照检查材料思想汇报
2014/09/21 职场文书
2014年标准化工作总结
2014/12/17 职场文书
督导岗位职责范本
2015/04/10 职场文书
2016年幼儿园教师师德承诺书
2016/03/25 职场文书
Python调用腾讯API实现人脸身份证比对功能
2022/04/04 Python
Python中re模块的元字符使用小结
2022/04/07 Python
Redis全局ID生成器的实现
2022/06/05 Redis