• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

php实例-浅谈PHP面向对象之访问者模式+组合模式

php 搞代码 4年前 (2022-01-22) 79次浏览 已收录 0个评论

下面小编就为大家带来一篇浅谈PHP面向对象之访问者模式+组合模式。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

因为原文中延续了组合模式的代码示例来讲访问者模式 所以这里就合并一起来复习了。但主要还是讲访问者模式。顾名思义这个模式会有一个访问者类(就像近期的热播剧“人民的名义”中的检查官,跑到到贪官家里调查取证,查实后就定罪),被访问者类调用访问者类的时候会将自身传递给它使用。

直接看代码:

//被访问者基类abstract class Unit {  abstract function bombardStrength();  //获取单位的攻击力    //这个方法将调用访问者类,并将自身传递给它  function accept(ArmyVisitor $visitor){    $method = "visit" . get_class($this);    $visitor->$method($this);      //调用访问者类的方法,这里使用了 "visit" . get_class($this) 组成了方法的名称  }    //按原文的说法是设置一个深度,虽然之后会有调用但这个方法对于理解这个模式不重要可以不用管他(原文示例代码中经常有些跟理解模式原理没太多关系的代码)  protected function setDepth($depth){    $this->depth = $depth;  }  function getDepth(){    return $this->depth;  }} //弓箭手class Archer extends Unit{  function bombardStrength(){    return 4;  }}//激光炮class LaserCannonUnit extends Unit{  function bombardStrength(){    return 44;  }}//骑兵class Cavalry extends Unit{  function bombardStrength(){    return 2;          //骑兵的攻击力居然比弓箭手低?  }} //用于组合继承了unit类的实例,并让Army和TroopCarrier类继承removeUnit和addUnit方法,不放基类是因为上述的三个类已经是最小单位了不是一个军事集团removeUnit和addUnit方法对他们没用。abstract class CompositeUnit extends Unit{  private $units = array();    //存放任何继承了unit 类的实例  function getComposite(){   //这个方法主要用于判断当前实例是否是一个 CompositeUnit 类    return $this;  }  protected function units(){    return $this->units;  }  function removeUnit(Unit $unit){    //删除一个军事单位    $this->units = array_udiff(      $this->units,array($unit),      function($a,$b){return ($a === $b)?0:1;}    );    }  function addUnit(Unit $unit){        //添加一个军事单位    if(in_array($unit,$this->units,true)){      return;    }    $unit->setDepth($this->depth + 1);      $this->units[] = $unit;  }  function bombardStrength(){    $ret = 0;    foreach($this->units as $unit){      $ret +=$unit->bombardStrength();    }    return $ret;  }  function accept(Armyvisitor $visitor){    //调用访问者    parent::accept($visitor);        //调用基类的accept方法,在第一个客户端代码条用里将会保存军事集团整体的一个信息    foreach($this->units as $thisunit){   //调用军事单位accept方法,在第一个客户端代码条用里将会保存其中每一个军事单位的信息      $thisunit->accept($visitor);    }  }	} //军队class Army extends CompositeUnit {}//舰队class TroopCarrier extends CompositeUnit {} //访问者类abstract class ArmyVisitor{  abstract function visit(Unit $node);  //访问者要执行的业务逻辑  function visitArcher(Archer $node){  //其实我觉得对于理解来说这个抽象类有一个抽象方法visit()就够了,原文还多出下面这些方法来绕个圈调用visit    //......     $this->visit($node);  }  function visitCavalry(Cavalry $node){    //.......    $this->visit($node);  }  function visitLaserCannonUnit(LaserCannonUnit $node){    //......    $this->visit($node);  }  function visitTroopCarrierUnit(Cavalry $node){    //......    $this->visit($node);  }  function visitArmy(Cavalry $node){    //......    $this->visit($node);  }}//这个访问者类主要用于获取并保存被访问者对象的信息class TextDumpArmyVisitor extends ArmyVisitor {  private $text = "";  function visit(Unit $node){    $ret = "";    $pad = 4 * $node->getDpth();    $ret .= sprintf("%{$pad}s","");    $ret .=get_class($node).": ";    $ret .= "bombard: " . $node->bombardStrength() . "\n";    $this->text .=$ret;  }  function getText(){    return $this->text;  }}//用于向每个对象征税的访问者类,客户端代码2中将会调用class TaxCollectionVisitor extends ArmyVisitor{  private $due=0;  private $report ="";  function visit(Unit $node){    $this->levy($node,1);  }  function visitArcher(Archer $node){    //复写了父类的方法,对于不同的单位征收不同的税    $this->levy($node,2);  }  function visitCavalry(Cavalry $node){    $this->levy($node,3);  }  function visitTroopCarrierUnit(TroopCarrierUnit $node){    $this->levy($node,5);  }  private function levy(Unit $unit,$amount){        //主要的业务逻辑    $this->report .= "Tax levied for" . get_class($unit);    $this->report .= ": $amount\n";    $this->due +=$amount;  }  function getReport(){    return $this->report;  }  function getTax(){    return $this->due;  }}//客户端代码1(获取并输出每个对象的一些信息)class UnitScript {  static function joinExisting(Unit $newUnit<p style="color:transparent">。本文来源gao!%daima.com搞$代*!码网1</p><cite>搞代gaodaima码</cite>,Unit $occupyingUnit){    $comp;    if(!is_null($com = $occupyingUnit->getComposite())){      $comp->addUnit($newUnit);    } else {      $comp = new Army();      $comp->addUnit($occupyingUnit);      $com->addUnit($newUnit);    }    return $comp;  }} $main_army = new Army();UnitScript::joinExisting(new Archer(),$main_army);UnitScript::joinExisting(new LaserCannonUnit(),$main_army);UnitScript::joinExisting(new Cavalry(),$main_army);$textdump = new TextDumpArmyVisitor();$main_army->accept($textdump);print $textdump->getText(); //客户端代码2(对每个对象征税,最后输出总共征收了多少)$main_army = new Army();UnitScript::joinExisting(new Archer(),$main_army);UnitScript::joinExisting(new LaserCannonUnit(),$main_army);UnitScript::joinExisting(new Cavalry(),$main_army);$taxcollector = new TaxCollectionVisitor();$main_army->accept($taxcollector);print $taxcollector->getTax();    //上述的代码因为太懒没测试,抱歉! 感兴趣的朋友就自己运行调试一下吧!

以上就是php实例-浅谈PHP面向对象之访问者模式+组合模式的详细内容,更多请关注搞代码gaodaima其它相关文章!


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:php实例-浅谈PHP面向对象之访问者模式+组合模式
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址