因?yàn)樵闹醒永m(xù)了組合模式的代碼示例來(lái)講訪(fǎng)問(wèn)者模式 所以這里就合并一起來(lái)復(fù)習(xí)了。但主要還是講訪(fǎng)問(wèn)者模式。顧名思義這個(gè)模式會(huì)有一個(gè)訪(fǎng)問(wèn)者類(lèi)(就像近期的熱播劇“人民的名義”中的檢查官,跑到到貪官家里調(diào)查取證,查實(shí)后就定罪),被訪(fǎng)問(wèn)者類(lèi)調(diào)用訪(fǎng)問(wèn)者類(lèi)的時(shí)候會(huì)將自身傳遞給它使用。
直接看代碼:
//被訪(fǎng)問(wèn)者基類(lèi) abstract class Unit { abstract function bombardStrength(); //獲取單位的攻擊力 //這個(gè)方法將調(diào)用訪(fǎng)問(wèn)者類(lèi),并將自身傳遞給它 function accept(ArmyVisitor $visitor){ $method = "visit" . get_class($this); $visitor->$method($this); //調(diào)用訪(fǎng)問(wèn)者類(lèi)的方法,這里使用了 "visit" . get_class($this) 組成了方法的名稱(chēng) } //按原文的說(shuō)法是設(shè)置一個(gè)深度,雖然之后會(huì)有調(diào)用但這個(gè)方法對(duì)于理解這個(gè)模式不重要可以不用管他(原文示例代碼中經(jīng)常有些跟理解模式原理沒(méi)太多關(guān)系的代碼) 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類(lèi)的實(shí)例,并讓Army和TroopCarrier類(lèi)繼承removeUnit和addUnit方法,不放基類(lèi)是因?yàn)樯鲜龅娜齻€(gè)類(lèi)已經(jīng)是最小單位了不是一個(gè)軍事集團(tuán)removeUnit和addUnit方法對(duì)他們沒(méi)用。 abstract class CompositeUnit extends Unit{ private $units = array(); //存放任何繼承了unit 類(lèi)的實(shí)例 function getComposite(){ //這個(gè)方法主要用于判斷當(dāng)前實(shí)例是否是一個(gè) CompositeUnit 類(lèi) return $this; } protected function units(){ return $this->units; } function removeUnit(Unit $unit){ //刪除一個(gè)軍事單位 $this->units = array_udiff( $this->units,array($unit), function($a,$b){return ($a === $b)?0:1;} ); } function addUnit(Unit $unit){ //添加一個(gè)軍事單位 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){ //調(diào)用訪(fǎng)問(wèn)者 parent::accept($visitor); //調(diào)用基類(lèi)的accept方法,在第一個(gè)客戶(hù)端代碼條用里將會(huì)保存軍事集團(tuán)整體的一個(gè)信息 foreach($this->units as $thisunit){ //調(diào)用軍事單位accept方法,在第一個(gè)客戶(hù)端代碼條用里將會(huì)保存其中每一個(gè)軍事單位的信息 $thisunit->accept($visitor); } } } //軍隊(duì) class Army extends CompositeUnit { } //艦隊(duì) class TroopCarrier extends CompositeUnit { } //訪(fǎng)問(wèn)者類(lèi) abstract class ArmyVisitor{ abstract function visit(Unit $node); //訪(fǎng)問(wèn)者要執(zhí)行的業(yè)務(wù)邏輯 function visitArcher(Archer $node){ //其實(shí)我覺(jué)得對(duì)于理解來(lái)說(shuō)這個(gè)抽象類(lèi)有一個(gè)抽象方法visit()就夠了,原文還多出下面這些方法來(lái)繞個(gè)圈調(diào)用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); } } //這個(gè)訪(fǎng)問(wèn)者類(lèi)主要用于獲取并保存被訪(fǎng)問(wèn)者對(duì)象的信息 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; } } //用于向每個(gè)對(duì)象征稅的訪(fǎng)問(wèn)者類(lèi),客戶(hù)端代碼2中將會(huì)調(diào)用 class TaxCollectionVisitor extends ArmyVisitor{ private $due=0; private $report =""; function visit(Unit $node){ $this->levy($node,1); } function visitArcher(Archer $node){ //復(fù)寫(xiě)了父類(lèi)的方法,對(duì)于不同的單位征收不同的稅 $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){ //主要的業(yè)務(wù)邏輯 $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; } } //客戶(hù)端代碼1(獲取并輸出每個(gè)對(duì)象的一些信息) 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(); //客戶(hù)端代碼2(對(duì)每個(gè)對(duì)象征稅,最后輸出總共征收了多少) $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(); //上述的代碼因?yàn)樘珣袥](méi)測(cè)試,抱歉! 感興趣的朋友就自己運(yùn)行調(diào)試一下吧!
以上這篇淺談PHP面向?qū)ο笾L(fǎng)問(wèn)者模式+組合模式就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持。
【網(wǎng)站聲明】本站除付費(fèi)源碼經(jīng)過(guò)測(cè)試外,其他素材未做測(cè)試,不保證完整性,網(wǎng)站上部分源碼僅限學(xué)習(xí)交流,請(qǐng)勿用于商業(yè)用途。如損害你的權(quán)益請(qǐng)聯(lián)系客服QQ:2655101040 給予處理,謝謝支持。