在之前的文章《PHP中什麼是狀態模式?透過實例來了解它》中我們介紹了PHP中的狀態模式,以下這篇文章帶大家了解PHP設計模式中的訪客模式。
訪問者,就像我們去別人家訪問,或別人來我們家探望我們一樣。我們每個人都像是一個實體,而來訪的人都會一一的和我們打招呼。畢竟,我們中華民族是非常講究禮數和好客的民族。訪客是GoF23個設計模式中最複雜的模式,也是各類設計模式教材放在最後的模式。先不管難度如何,我們先來看看它的定義和實現。
GoF定義:表示一個作用於某物件結構中的各元素的操作。它使你可以在不改變各元素的類別的前提下定義作用於這些元素的新操作
#GoF類別圖
程式碼實作
interface Visitor { public function VisitConcreteElementA(ConcreteElementA $a); function VisitConcreteElementB(ConcreteElementB $b); } class ConcreteVisitor1 implements Visitor { public function VisitConcreteElementA(ConcreteElementA $a) { echo get_class($a) . "被" . get_class($this) . "访问", PHP_EOL; } public function VisitConcreteElementB(ConcreteElementB $b) { echo get_class($b) . "被" . get_class($this) . "访问", PHP_EOL; } } class ConcreteVisitor2 implements Visitor { public function VisitConcreteElementA(ConcreteElementA $a) { echo get_class($a) . "被" . get_class($this) . "访问", PHP_EOL; } public function VisitConcreteElementB(ConcreteElementB $b) { echo get_class($b) . "被" . get_class($this) . "访问", PHP_EOL; } }
抽象的訪客介面及兩個具體實作。可以看作是一家小兩口來我們家作客咯!
interface Element { public function Accept(Visitor $v); } class ConcreteElementA implements Element { public function Accept(Visitor $v) { $v->VisitConcreteElementA($this); } public function OperationA() { } } class ConcreteElementB implements Element { public function Accept(Visitor $v) { $v->VisitConcreteElementB($this); } public function OperationB() { } }
元素抽象化及實現,也可以看作是要存取的實體。當然就是我跟我媳婦啦。
class ObjectStructure { private $elements = []; public function Attach(Element $element) { $this->elements[] = $element; } public function Detach(Element $element) { $position = 0; foreach ($this->elements as $e) { if ($e == $element) { unset($this->elements[$position]); break; } $position++; } } public function Accept(Visitor $visitor) { foreach ($this->elements as $e) { $e->Accept($visitor); } } }
這是一個物件結構,用於保存元素實體並進行存取呼叫。大家在客廳見面,互相寒暄嘛,這裡就是個客廳
$o = new ObjectStructure(); $o->Attach(new ConcreteElementA()); $o->Attach(new ConcreteElementB()); $v1 = new ConcreteVisitor1(); $v2 = new ConcreteVisitor2(); $o->Accept($v1); $o->Accept($v2);
客戶端的調用,總算讓大家正式見面了,互相介紹握手。一次訪問就愉快的完成了。
我們公司的帳務,只有收入和支出兩項(Element),但不同的部門(Visitor)存取的時候會給出不同的內容。例如我查看的時候只需要查看每月或每季的總數據即可,財務總監則需要詳細的收支記錄,而會計在做帳時更是需要完整的明細。可見,公司的營運真的是需要非常廣泛的知識的,不僅是管理能力,帳務知識也是必要了解的內容! !
完整程式碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/23.visitor/source/visitor.php
最後一個模式的範例還是回到我們的訊息傳送上。同樣的還是多個服務商,它們作為訪客需要去使用各自的簡訊發送及APP推送介面。這時,就可以使用訪客模式來進行操作,實現這些訪客的全部操作。
訪客模式資訊發送
#完整原始碼:https://github.com/zhangyue0503/designpatterns- php/blob/master/23.visitor/source/visitor-msg.php
<?php interface ServiceVisitor { public function SendMsg(SendMessage $s); function PushMsg(PushMessage $p); } class AliYun implements ServiceVisitor { public function SendMsg(SendMessage $s) { echo '阿里云发送短信!', PHP_EOL; } public function PushMsg(PushMessage $p) { echo '阿里云推送信息!', PHP_EOL; } } class JiGuang implements ServiceVisitor { public function SendMsg(SendMessage $s) { echo '极光发送短信!', PHP_EOL; } public function PushMsg(PushMessage $p) { echo '极光推送短信!', PHP_EOL; } } interface Message { public function Msg(ServiceVisitor $v); } class PushMessage implements Message { public function Msg(ServiceVisitor $v) { echo '推送脚本启动:'; $v->PushMsg($this); } } class SendMessage implements Message { public function Msg(ServiceVisitor $v) { echo '短信脚本启动:'; $v->SendMsg($this); } } class ObjectStructure { private $elements = []; public function Attach(Message $element) { $this->elements[] = $element; } public function Detach(Message $element) { $position = 0; foreach ($this->elements as $e) { if ($e == $element) { unset($this->elements[$position]); break; } $position++; } } public function Accept(ServiceVisitor $visitor) { foreach ($this->elements as $e) { $e->Msg($visitor); } } } $o = new ObjectStructure(); $o->Attach(new PushMessage()); $o->Attach(new SendMessage()); $v1 = new AliYun(); $v2 = new JiGuang(); $o->Accept($v1); $o->Accept($v2);
說明
原文地址:https://juejin.cn/post/6844903993240453133
作者:硬核心項目經理
推薦學習:《PHP影片教學》
以上是深入淺析PHP中的訪客模式的詳細內容。更多資訊請關注PHP中文網其他相關文章!