久久96国产精品久久久-久久发布国产伦子伦精品-久久精品国产精品青草-久久天天躁夜夜躁狠狠85麻豆

技術員聯盟提供win764位系統下載,win10,win7,xp,裝機純凈版,64位旗艦版,綠色軟件,免費軟件下載基地!

當前位置:主頁 > 教程 > 服務器類 >

PHP面向對象之訪問者模式+組合模式

來源:技術員聯盟┆發布時間:2017-09-23 18:05┆點擊:

因為原文中延續了組合模式的代碼示例來講訪問者模式 所以這里就合并一起來復習了。但主要還是講訪問者模式。顧名思義這個模式會有一個訪問者類(就像近期的熱播劇“人民的名義”中的檢查官,跑到到貪官家里調查取證,查實后就定罪),被訪問者類調用訪問者類的時候會將自身傳遞給它使用。

直接看代碼:

//被訪問者基類 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();