轻松掌握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 相关文章推荐
实用函数2
Nov 08 PHP
PHP 多进程 解决难题
Jun 22 PHP
关于session在PHP5的配置文件中的详细设置参数说明
Apr 20 PHP
php中数组首字符过滤功能代码
Jul 31 PHP
PHP中实现获取IP和地理位置类分享
Feb 10 PHP
举例讲解PHP面对对象编程的多态
Aug 12 PHP
PHP扩展开发教程(总结)
Nov 04 PHP
PHP下载远程图片并保存到本地方法总结
Jan 22 PHP
PHP编写的图片验证码类文件分享
Jun 06 PHP
thinkPHP5.0框架开发规范简介
Mar 25 PHP
PHP实现将多个文件压缩成zip格式并下载到本地的方法示例
May 23 PHP
Laravel中GraphQL接口请求频率实战记录
Sep 01 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初学者最感迷茫的问题小结
2010/03/27 PHP
CentOS下PHP安装Oracle扩展
2015/02/15 PHP
使用新的消息弹出框blackbirdjs
2008/10/16 Javascript
JavaScript 对象、函数和继承
2009/07/07 Javascript
jQuery判断元素是否是隐藏的代码
2011/04/24 Javascript
js常用自定义公共函数汇总
2014/01/15 Javascript
javascript中setInterval的用法
2015/07/19 Javascript
jQuery实现根据滚动条位置加载相应内容功能
2016/07/18 Javascript
关于javascript sort()排序你可能忽略的一点理解
2017/07/18 Javascript
Vue+webpack项目基础配置教程
2018/02/12 Javascript
解决angularJS中input标签的ng-change事件无效问题
2018/09/13 Javascript
Element-ui DatePicker显示周数的方法示例
2019/07/19 Javascript
NodeJS有难度的面试题(能答对几个)
2019/10/09 NodeJs
vue-router重写push方法,解决相同路径跳转报错问题
2020/08/07 Javascript
详解Vue.js3.0 组件是如何渲染为DOM的
2020/11/10 Javascript
Python中的字符串替换操作示例
2016/06/27 Python
Python实现针对中文排序的方法
2017/05/09 Python
用virtualenv建立多个Python独立虚拟开发环境
2017/07/06 Python
详解python中的json和字典dict
2018/06/22 Python
python反编译学习之字节码详解
2019/05/19 Python
Python使用Beautiful Soup爬取豆瓣音乐排行榜过程解析
2019/08/15 Python
爬虫代理池Python3WebSpider源代码测试过程解析
2019/12/20 Python
记录一下scrapy中settings的一些配置小结
2020/09/28 Python
python 中关于pycharm选择运行环境的问题
2020/10/31 Python
Python 实现PS滤镜中的径向模糊特效
2020/12/03 Python
python利用proxybroker构建爬虫免费IP代理池的实现
2021/02/21 Python
香港太阳眼镜网上商店:SmartBuyGlasses香港
2016/07/22 全球购物
荷兰在线体育用品商店:Avantisport.nl
2018/07/04 全球购物
巴西电子、家电、智能手机购物网站:Girafa
2019/06/04 全球购物
EJB的角色和三个对象
2015/12/31 面试题
大学生自我鉴定范文模板
2014/01/21 职场文书
咖啡馆创业计划书
2014/01/26 职场文书
计算机应届毕业生自荐信范文
2014/02/23 职场文书
助人为乐模范事迹材料
2014/06/02 职场文书
小学教师见习总结
2015/06/23 职场文书
创业计划书之情侣餐厅
2019/09/29 职场文书