PHP Object-oriented visitor pattern + Combo mode

Source: Internet
Author: User
Tags gettext

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:

By visitor base class

Abstract class Unit {
Abstract function bombardstrength (); Get the unit's attack power
  

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) The name of the method
}
  

According to the original word is to set a depth, although it will be called later, 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 does not have much to do with 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 that inherit the Unit class

function Getcomposite () {//This method is primarily used to determine whether the current 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); Calling the Accept method of the base class, in the first client code strip, will save a message for the military group as a whole
foreach ($this->units as $thisunit) {//Call the military unit accept method, in which the first client code strip will hold information about each of these military units
$thisunit->accept ($visitor);
}
}
}

Army

Class Army extends Compositeunit {

}

Fleet

Class Troopcarrier extends Compositeunit {

}

Visitor class

Abstract class armyvisitor{
Abstract function Visit (Unit $node); Business logic that visitors want to execute
function Visitarcher (Archer $node) {//In fact, I think this abstract class has an abstract method for understanding visit () is enough, the original text more than the following methods to call around a circle 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 get and save information about the object being accessed by
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, which will be called in client code 2
Class Taxcollectionvisitor extends armyvisitor{
private $due =0;
Private $report = "";  

Function Visit (Unit $node) {
$this->levy ($node, 1);
  

Function Visitarcher (Archer $node) {//The method of the parent class is replicated, different taxes are levied for different units
$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) {//Primary business logic
$this->report. = "levied for". Get_c Lass ($unit);
$this->report. = ": $amount \ n";
$this->due + = $amount;  
}

Function GetReport () {
return $this->report;
  

Function Gettax () {
return $this->due;
}
}


Client code 1 (GET and output 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);
Print $textdump->gettext ();

Client Code 2 (tax each object, the total amount of the final output)
$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 ();

The above code because too lazy did not test, sorry! Interested friends on their own run debugging it!

PHP Object-oriented visitor pattern + Combo mode

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.