淺談PHP面向?qū)ο笾L問者模式+組合模式
因?yàn)樵闹醒永m(xù)了組合模式的代碼示例來講訪問者模式 所以這里就合并一起來復(fù)習(xí)了。但主要還是講訪問者模式。顧名思義這個(gè)模式會(huì)有一個(gè)訪問者類,被訪問者類調(diào)用訪問者類的時(shí)候會(huì)將自身傳遞給它使用。
直接看代碼:
//被訪問者基類
abstract class Unit {
abstract function bombardStrength(); //獲取單位的攻擊力
//這個(gè)方法將調(diào)用訪問者類,并將自身傳遞給它
function accept(ArmyVisitor $visitor){
$method = "visit" . get_class($this);
$visitor->$method($this); //調(diào)用訪問者類的方法,這里使用了 "visit" . get_class($this) 組成了方法的名稱
}
//按原文的說法是設(shè)置一個(gè)深度,雖然之后會(huì)有調(diào)用但這個(gè)方法對(duì)于理解這個(gè)模式不重要可以不用管他(原文示例代碼中經(jīng)常有些跟理解模式原理沒太多關(guān)系的代碼)
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類的實(shí)例,并讓Army和TroopCarrier類繼承removeUnit和addUnit方法,不放基類是因?yàn)樯鲜龅娜齻€(gè)類已經(jīng)是最小單位了不是一個(gè)軍事集團(tuán)removeUnit和addUnit方法對(duì)他們沒用。
abstract class CompositeUnit extends Unit{
private $units = array(); //存放任何繼承了unit 類的實(shí)例
function getComposite(){ //這個(gè)方法主要用于判斷當(dāng)前實(shí)例是否是一個(gè) 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){ //調(diào)用訪問者
parent::accept($visitor);
foreach($this->units as $thisunit){
$thisunit->accept($visitor);
}
}
}
class Army extends CompositeUnit {
}
class TroopCarrier extends CompositeUnit {
}
//訪問者類
abstract class ArmyVisitor{
abstract function visit(Unit $node); //訪問者要執(zhí)行的業(yè)務(wù)邏輯
function visitArcher(Archer $node){ //其實(shí)我覺得對(duì)于理解來說這個(gè)抽象類有一個(gè)抽象方法visit()就夠了,原文還多出下面這些方法來繞個(gè)圈調(diào)用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);
}
}
//這個(gè)訪問者類主要用于獲取并保存被訪問者對(duì)象的信息
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;
}
}
class TaxCollectionVisitor extends ArmyVisitor{
private $due=0;
private $report ="";
function visit(Unit $node){
$this->levy($node,1);
}
function visitArcher(Archer $node){ //復(fù)寫了父類的方法,對(duì)于不同的單位征收不同的稅
$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){ //主要的業(yè)務(wù)邏輯
$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(獲取并輸出每個(gè)對(duì)象的一些信息)
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();
$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();
//上述的代碼因?yàn)樘珣袥]測(cè)試,抱歉! 感興趣的朋友就自己運(yùn)行調(diào)試一下吧!以上這篇淺談PHP面向?qū)ο笾L問者模式+組合模式就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
php實(shí)現(xiàn)微信支付之現(xiàn)金紅包
這篇文章主要為大家詳細(xì)介紹了php實(shí)現(xiàn)微信支付之現(xiàn)金紅包,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05
Yii CDBCriteria常用方法實(shí)例小結(jié)
這篇文章主要介紹了Yii CDBCriteria常用方法,結(jié)合實(shí)例形式總結(jié)分析了CDBCriteria類的功能與常用方法,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2017-01-01
thinkPHP顯示不出驗(yàn)證碼的原因與解決方法分析
這篇文章主要介紹了thinkPHP顯示不出驗(yàn)證碼的原因與解決方法,結(jié)合具體實(shí)例形式分析了thinkPHP關(guān)于驗(yàn)證碼顯示的相關(guān)配置方法與注意事項(xiàng),需要的朋友可以參考下2017-05-05
thinkPHP5.0框架事務(wù)處理操作簡(jiǎn)單示例
這篇文章主要介紹了thinkPHP5.0框架事務(wù)處理操作,結(jié)合實(shí)例形式分析了thinkPHP5針對(duì)刪除操作的事務(wù)處理相關(guān)操作技巧,需要的朋友可以參考下2018-09-09
php項(xiàng)目接入xxl-job調(diào)度系統(tǒng)的示例詳解
這篇文章主要介紹了php項(xiàng)目接入xxl-job調(diào)度系統(tǒng)的示例代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12
PHP使用openssl擴(kuò)展實(shí)現(xiàn)加解密方法示例
這篇文章主要介紹了PHP使用openssl擴(kuò)展實(shí)現(xiàn)加解密方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02
PHP使用Session遇到的一個(gè)Permission denied Notice解決辦法
這篇文章主要介紹了PHP使用Session遇到的一個(gè)Permission denied Notice解決辦法,本文系統(tǒng)環(huán)境是ubuntu、Debian系統(tǒng),有很小的概率會(huì)遇到這個(gè)提示,需要的朋友可以參考下2014-07-07
thinkPHP5框架實(shí)現(xiàn)基于ajax的分頁功能示例
這篇文章主要介紹了thinkPHP5框架實(shí)現(xiàn)基于ajax的分頁功能,結(jié)合實(shí)例形式分析了thinkPHP5框架上進(jìn)行ajax分頁操作的具體步驟、實(shí)現(xiàn)代碼與相關(guān)操作方法,需要的朋友可以參考下2018-06-06

