浅谈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,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面向对象之访问者模式+组合模式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

时间: 2024-10-23 05:37:06

浅谈PHP面向对象之访问者模式+组合模式的相关文章

中小网站的收益浅谈:关于流量转化和盈利模式

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 本文的主要内容是说下个人对网站的流量.盈利模式和其收益之间关系的浅薄认识,在这之前,先解释一下这四个概念.首先是网站的流量,也就是网站的访问量,一般有IP.PV.UV等方式来统计访问量的大小,IP是指网站获得了来自不同IP的的访问,一个IP访问则记录一个IP.UV是指网站的独立访客,它记录的独立的cookie数,也就是访问网站的独立的计算机数

圈圈-浅谈个人网站发展和赚钱的模式-选择篇

个人网站|赚钱  做站前你要估计你自己的能力适合做什么站,金钱,技术和网络运行方面的知识和你的长期积累的经验有多少,这个是很关键的!我们不去谈那些经济实力很强和那些专业提供技术服务的站点,我所谈的是在网络中盲目徘徊的站长你们应该怎么样去做站和去赚钱,希望从中可以对那些没有发展起来的站长给予一种启发,因为我相信个人站长永远比公司的来的强,无论在工作时间和勤奋态度上都是行业的佼佼者!      首先你要去考虑你想做什么,通过那些渠道去赚钱,你准备投资多少,你想出名还是只想赚钱还是想两者皆顾?这个问题

浅谈教育培训类网站的盈利模式

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 随着我国网络的不断普及,教育培训类网站也有了很大的市场,目前我国的考试大大小小不计其数,包括资格考试如计算机级别考试,司法考试,注册会计师考试等.认证考试类考试如cisco考试等,那么随着我国远程教育的不断发展,教育培训类网站该怎样发展呢?应该以怎样的模式去盈利呢?以下是本人的一些拙见: 1. 首先在确定盈利模式之前,我们应当使我们的网站有以

浅谈javascript 面向对象编程_js面向对象

感叹是为了缓解严肃的气氛并引出今天要讲的话题,"javascript面向对象编程",接下来,我们围绕面向对象的几大关键字:封装,继承,多态,展开. 封装:javascript中创建对象的模式中,个人认为通过闭包才算的上是真正意义上的封装,所以首先我们先来简单介绍一下闭包,看下面这个例子: 复制代码 代码如下: <script type="text/javascript"> function myInfo(){ var name ="老鱼&quo

老鱼 浅谈javascript面向对象编程_js面向对象

感叹是为了缓解严肃的气氛并引出今天要讲的话题,"javascript面向对象编程",接下来,我们围绕面向对象的几大关键字:封装,继承,多态,展开. 封装:javascript中创建对象的模式中,个人认为通过闭包才算的上是真正意义上的封装,所以首先我们先来简单介绍一下闭包,看下面这个例子: 复制代码 代码如下: <script type="text/javascript">// <![CDATA[ function myInfo(){ var nam

浅谈现代企业中性能分析的反模式

什么是性能分析 "性能分析"一词有许多种定义,但在我看来最有用的一个是: 一种由测量驱动的方法,用以了解一个应用程序在负载下的行为. 这个定义的好处是,它提醒您注意测量是整个过程的关键点.并通过简单的延伸,也提醒您统计和数据分析可能是性能工程师的重要工具. 进一步讲,它使我们更相信应把性能分析看作是一项基础的实证研究活动,是它把输入和输出粘合在一起组成实验科学. 这样,这些输出就可以被框定为一系列具有量化答案的问题,比如: 如果有10倍的客户数,系统还有足够的内存来应付吗? 在客户看来

浅谈软件下载站有哪些盈利模式

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 虽然说现在的软件下载站不像之前那么火爆了,不过软件下载网站的盈利模式却有很多,所以对很多个人站长的吸引力还是比较大的,下面就让笔者给大家介绍几种常见的软件下载站的盈利模式!希望能够给大家做一下参考! 一:利用弹窗广告的模式来赚钱,虽然弹窗广告这种模式已经被很多正规的网站所抛弃了,不过对于垃圾网站来说还是有相当不错的诱惑力的,很多下载类的网站可

浅谈互联网未来站长发展的新模式

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 古有曹刘孙瓜分天下魏蜀吴,今有曹丁张瓜分门户新网狐.三国争分天下曹操终成一霸,而门户多争始终未分夺胜负,各霸一方,三国多年奋战,遭殃的无疑是百姓,互联网局势随不能以奋战来形容,暂且不提门户,只讲站长风云.2009年某年某月,互联网迎来了冬天,这个冬天是突然袭击,以至于部分站长都未做好防寒准备,就被一刀切的方式给打入了冷宫,本人也是站长之一,深

浅谈三种C2B电商的模式

在过去的一年中,电商领域可谓是血雨腥风,尤其是天猫.京东.苏宁.当当.易讯等B2C电商之间的战争.伴随着B2C领域竞争进入白热化阶段,C2B模式也在天猫"双11"的预售后,渐渐被很多人知道. 如今的中国电商市场,毫无疑问,C2C领域淘宝是绝对王者,B2C领域中平台式的天猫也是第一,而自主式的京东.易讯.苏宁等几家在争夺第二的路上,并没有给其它人机会,但是目前的C2B领域还是有一定的空白,C2B领域可能会是电商的另一条路或下一个方向吗? 其实C2B的概念是很泛化,形式也是有很多种,一号店