首页 > PHP教程 > php开发知识文章

PHP设计模式之访问者模式和组合模式

下面小编就为大家带来一篇PHP设计模式之访问者模式和组合模式。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

访问者模式(Visitor Pattern)

是GoF提出的23种设计模式中的一种,属于行为模式。算是最复杂也是最难以理解的一种模式了。

定义:表示一个作用于某对象结构中的各元素的操作。它使你在不改变各元素类的前提下定义作用于这些元素的新操作。

访问者模式,这个模式会有一个访问者类,被访问者类调用访问者类的时候会将自身传递给它使用。

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类的实例,并让ArmyTroopCarrier类继承removeUnitaddUnit方法,
//不放基类是因为上述的三个类已经是最小单位了不是一个军事集团removeUnitaddUnit方法对他们没用。

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){
//......
$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(Cavalry $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){
if(!is_null($com = $occupyingUnit->getComposite())){
$com->addUnit($newUnit);
} else {
$comp = new Army();
$comp->addUnit($occupyingUnit);
$comp->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设计模式之访问者模式和组合模式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持本站。

PHP历史版本

关闭
感谢您的支持,我会继续努力!
扫码打赏,建议金额1-10元


提醒:打赏金额将直接进入对方账号,无法退款,请您谨慎操作。