浅谈PHP面向对象之访问者模式+组合模式
因为原文中延续了组合模式的代码示例来讲访问者模式所以这里就合并一起来复习了。但主要还是讲访问者模式。顾名思义这个模式会有一个访问者类(就像近期的热播剧“人民的名义”中的检查官,跑到到贪官家里调查取证,查实后就定罪),被访问者类调用访问者类的时候会将自身传递给它使用。
直接看代码:
//被访问者基类
abstractclassUnit{
abstractfunctionbombardStrength();//获取单位的攻击力
//这个方法将调用访问者类,并将自身传递给它
functionaccept(ArmyVisitor$visitor){
$method="visit".get_class($this);
$visitor->$method($this);//调用访问者类的方法,这里使用了"visit".get_class($this)组成了方法的名称
}
//按原文的说法是设置一个深度,虽然之后会有调用但这个方法对于理解这个模式不重要可以不用管他(原文示例代码中经常有些跟理解模式原理没太多关系的代码)
protectedfunctionsetDepth($depth){
$this->depth=$depth;
}
functiongetDepth(){
return$this->depth;
}
}
//弓箭手
classArcherextendsUnit{
functionbombardStrength(){
return4;
}
}
//激光炮
classLaserCannonUnitextendsUnit{
functionbombardStrength(){
return44;
}
}
//骑兵
classCavalryextendsUnit{
functionbombardStrength(){
return2;//骑兵的攻击力居然比弓箭手低?
}
}
//用于组合继承了unit类的实例,并让Army和TroopCarrier类继承removeUnit和addUnit方法,不放基类是因为上述的三个类已经是最小单位了不是一个军事集团removeUnit和addUnit方法对他们没用。
abstractclassCompositeUnitextendsUnit{
private$units=array();//存放任何继承了unit类的实例
functiongetComposite(){//这个方法主要用于判断当前实例是否是一个CompositeUnit类
return$this;
}
protectedfunctionunits(){
return$this->units;
}
functionremoveUnit(Unit$unit){//删除一个军事单位
$this->units=array_udiff(
$this->units,array($unit),
function($a,$b){return($a===$b)?0:1;}
);
}
functionaddUnit(Unit$unit){//添加一个军事单位
if(in_array($unit,$this->units,true)){
return;
}
$unit->setDepth($this->depth+1);
$this->units[]=$unit;
}
functionbombardStrength(){
$ret=0;
foreach($this->unitsas$unit){
$ret+=$unit->bombardStrength();
}
return$ret;
}
functionaccept(Armyvisitor$visitor){//调用访问者
parent::accept($visitor);//调用基类的accept方法,在第一个客户端代码条用里将会保存军事集团整体的一个信息
foreach($this->unitsas$thisunit){//调用军事单位accept方法,在第一个客户端代码条用里将会保存其中每一个军事单位的信息
$thisunit->accept($visitor);
}
}
}
//军队
classArmyextendsCompositeUnit{
}
//舰队
classTroopCarrierextendsCompositeUnit{
}
//访问者类
abstractclassArmyVisitor{
abstractfunctionvisit(Unit$node);//访问者要执行的业务逻辑
functionvisitArcher(Archer$node){//其实我觉得对于理解来说这个抽象类有一个抽象方法visit()就够了,原文还多出下面这些方法来绕个圈调用visit
//......
$this->visit($node);
}
functionvisitCavalry(Cavalry$node){
//.......
$this->visit($node);
}
functionvisitLaserCannonUnit(LaserCannonUnit$node){
//......
$this->visit($node);
}
functionvisitTroopCarrierUnit(Cavalry$node){
//......
$this->visit($node);
}
functionvisitArmy(Cavalry$node){
//......
$this->visit($node);
}
}
//这个访问者类主要用于获取并保存被访问者对象的信息
classTextDumpArmyVisitorextendsArmyVisitor{
private$text="";
functionvisit(Unit$node){
$ret="";
$pad=4*$node->getDpth();
$ret.=sprintf("%{$pad}s","");
$ret.=get_class($node).":";
$ret.="bombard:".$node->bombardStrength()."\n";
$this->text.=$ret;
}
functiongetText(){
return$this->text;
}
}
//用于向每个对象征税的访问者类,客户端代码2中将会调用
classTaxCollectionVisitorextendsArmyVisitor{
private$due=0;
private$report="";
functionvisit(Unit$node){
$this->levy($node,1);
}
functionvisitArcher(Archer$node){//复写了父类的方法,对于不同的单位征收不同的税
$this->levy($node,2);
}
functionvisitCavalry(Cavalry$node){
$this->levy($node,3);
}
functionvisitTroopCarrierUnit(TroopCarrierUnit$node){
$this->levy($node,5);
}
privatefunctionlevy(Unit$unit,$amount){//主要的业务逻辑
$this->report.="Taxleviedfor".get_class($unit);
$this->report.=":$amount\n";
$this->due+=$amount;
}
functiongetReport(){
return$this->report;
}
functiongetTax(){
return$this->due;
}
}
//客户端代码1(获取并输出每个对象的一些信息)
classUnitScript{
staticfunctionjoinExisting(Unit$newUnit,Unit$occupyingUnit){
$comp;
if(!is_null($com=$occupyingUnit->getComposite())){
$comp->addUnit($newUnit);
}else{
$comp=newArmy();
$comp->addUnit($occupyingUnit);
$com->addUnit($newUnit);
}
return$comp;
}
}
$main_army=newArmy();
UnitScript::joinExisting(newArcher(),$main_army);
UnitScript::joinExisting(newLaserCannonUnit(),$main_army);
UnitScript::joinExisting(newCavalry(),$main_army);
$textdump=newTextDumpArmyVisitor();
$main_army->accept($textdump);
print$textdump->getText();
//客户端代码2(对每个对象征税,最后输出总共征收了多少)
$main_army=newArmy();
UnitScript::joinExisting(newArcher(),$main_army);
UnitScript::joinExisting(newLaserCannonUnit(),$main_army);
UnitScript::joinExisting(newCavalry(),$main_army);
$taxcollector=newTaxCollectionVisitor();
$main_army->accept($taxcollector);
print$taxcollector->getTax();
//上述的代码因为太懒没测试,抱歉!感兴趣的朋友就自己运行调试一下吧!
以上这篇浅谈PHP面向对象之访问者模式+组合模式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。