PHP面向对象之访问者模式+组合模式
2018-06-22 05:19:11来源:未知 阅读 ()
因为原文中延续了组合模式的代码示例来讲访问者模式 所以这里就合并一起来复习了。但主要还是讲访问者模式。顾名思义这个模式会有一个访问者类(就像近期的热播剧“人民的名义”中的检查官,跑到到贪官家里调查取证,查实后就定罪),被访问者类调用访问者类的时候会将自身传递给它使用。直接看代码:
//被访问者基类
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类的实例,并让Army和TroopCarrier类继承removeUnit和addUnit方法,不放基类是因为上述的三个类已经是最小单位了不是一个军事集团removeUnit和addUnit方法对他们没用。
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){ //其实我觉得对于理解来说这个抽象类有一个抽象方法visit()就够了,原文还多出下面这些方法来绕个圈调用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);
}
}
//这个访问者类主要用于获取并保存被访问者对象的信息
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(TroopCarrierUnit $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){
$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();
//客户端代码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();
//上述的代码因为太懒没测试,抱歉! 感兴趣的朋友就自己运行调试一下吧!
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:php-人员权限管理(RBAC)
下一篇:linux启动流程简介
- PHP写UltraEdit插件脚本实现方法 2020-03-29
- php 带逗号千位符数字的处理方法 2020-03-28
- PHP三元运算符的结合性介绍 2020-03-28
- PHP静态延迟绑定和普通静态效率的对比 2020-03-28
- 基于php流程控制语句和循环控制语句 2020-03-28
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash