This article mainly introduces PHP object-oriented visitor patterns and the combination of patterns, interested in the reference of friends, I hope to help you.
Because the code example that continues the composition pattern in the original text is about the visitor pattern, it is merged here to review. But it's mostly about visitor patterns. As the name implies, this model will have a visitor class (like the recent hit drama "The Name of the people" in the inspector, ran to the corrupt officials at home to investigate evidence, verified after the conviction), the visitor class will be called when the visitor class will pass itself to its use.
Look directly at the code:
The visitor base class abstract class Unit {abstract function bombardstrength (); Gets the unit's attack//This method invokes the visitor class and passes itself to it function accept (Armyvisitor $visitor) {$method = "visit". Get_class ($this); $visitor-$method ($this); Call the method of the visitor class, where "visit" is used. Get_class ($this) consists of the name of the method}//According to the source of the text is set a depth, although there will be a call but this method is not important to understand this pattern can be done without him (there are often some code in the original sample code that is not much related to understanding the mode principle) protected function Setdepth ($depth) {$this->depth = $depth; } function Getdepth () {return $this->depth; }}//Archer class Archer extends unit{function bombardstrength () {return 4; }}//laser Cannon Class Lasercannonunit extends unit{function bombardstrength () {return 44; }}//Cavalry Class Cavalry extends unit{function bombardstrength () {return 2; The cavalry has a lower attack power than the archer? }}//Used to combine instances of the Unit class and let the army and Troopcarrier classes inherit the Removeunit and Addunit methods, The base class is not laid out because the above three classes are already the smallest units that are not a military group Removeunit and Addunit methods are useless to them. Abstract class Compositeunit extends unit{private $units = Array (); Store any instances of the Unit class that inherit function Getcomposite () {//This method is mainly used to determine the currentWhether the instance is a Compositeunit class return $this; } protected function units () {return $this->units; } function Removeunit (unit $unit) {//delete a military unit $this->units = Array_udiff ($this->units,array ($unit), function ($a, $b) {return ($a = = = $b)? 0:1;} ); } function Addunit (unit $unit) {//Add a military 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) {//Call visitor Parent::accept ($visitor); Call the base class accept method, in the first client code strip will save a message of the military group as a whole foreach ($this->units as $thisunit) {//Call the military unit accept method, The information for each of these military units will be saved in the first client code strip $thisunit->accept ($visitor); }}}//Army class Army extends Compositeunit {}//Fleet class Troopcarrier extends Compositeunit {}//Visitor class abstract class Armyvisi tor{ Abstract function Visit (Unit $node); Business logic function Visitarcher (Archer $node) that visitors want to execute {//In fact, I think this abstract class has an abstract method for understanding visit () is enough, the source of the following methods to call 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); }}//this visitor class is primarily used to obtain and save the information of the Visitor object 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; }}//the visitor class used to tax each object, the class Taxcollectionvisitor extends armyvisitor{p is called in client code 2Rivate $due = 0; Private $report = ""; function visit (Unit $node) {$this->levy ($node, 1); } function Visitarcher (Archer $node) {/////The method of copying the parent class, imposing different taxes on different units $this->levy ($node, 2); } function Visitcavalry (cavalry $node) {$this->levy ($node, 3); } function Visittroopcarrierunit (Troopcarrierunit $node) {$this->levy ($node, 5); The Private function levy (Unit $unit, $amount) {//main business logic $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; }}//Client code 1 (gets and outputs some information for each object) 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);p rint $textdump->gettext (); Client Code 2 (tax each object, how much of the final output is collected) $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);p rint $taxcollector->gettax (); The above code because too lazy did not test, sorry! Interested friends on their own run debugging it!