溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

PHP中怎么實(shí)現(xiàn)訪問(wèn)者模式

發(fā)布時(shí)間:2021-08-04 11:57:18 來(lái)源:億速云 閱讀:108 作者:Leah 欄目:編程語(yǔ)言

PHP中怎么實(shí)現(xiàn)訪問(wèn)者模式,相信很多沒(méi)有經(jīng)驗(yàn)的人對(duì)此束手無(wú)策,為此本文總結(jié)了問(wèn)題出現(xiàn)的原因和解決方法,通過(guò)這篇文章希望你能解決這個(gè)問(wèn)題。

Gof類(lèi)圖及解釋

GoF定義:表示一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作。它使你可以在不改變各元素的類(lèi)的前提下定義作用于這些元素的新操作

GoF類(lèi)圖

PHP中怎么實(shí)現(xiàn)訪問(wèn)者模式

代碼實(shí)現(xiàn)

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) . "訪問(wèn)", PHP_EOL;
    }
    public function VisitConcreteElementB(ConcreteElementB $b)
    {
        echo get_class($b) . "被" . get_class($this) . "訪問(wèn)", PHP_EOL;
    }
}

class ConcreteVisitor2 implements Visitor
{
    public function VisitConcreteElementA(ConcreteElementA $a)
    {
        echo get_class($a) . "被" . get_class($this) . "訪問(wèn)", PHP_EOL;
    }
    public function VisitConcreteElementB(ConcreteElementB $b)
    {
        echo get_class($b) . "被" . get_class($this) . "訪問(wèn)", PHP_EOL;
    }
}

抽象的訪問(wèn)者接口及兩個(gè)具體實(shí)現(xiàn)。可以看作是一家小兩口來(lái)我們家作客咯!

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()
    {

    }
}

元素抽象及實(shí)現(xiàn),也可以看作是要訪問(wèn)的實(shí)體。當(dāng)然就是我和我媳婦啦。

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);
        }
    }

}

這是一個(gè)對(duì)象結(jié)構(gòu),用于保存元素實(shí)體并進(jìn)行訪問(wèn)調(diào)用。大家在客廳里見(jiàn)面,互相寒暄嘛,這里就是個(gè)客廳

$o = new ObjectStructure();
$o->Attach(new ConcreteElementA());
$o->Attach(new ConcreteElementB());

$v1 = new ConcreteVisitor1();
$v2 = new ConcreteVisitor2();

$o->Accept($v1);
$o->Accept($v2);

客戶(hù)端的調(diào)用,總算讓大家正式見(jiàn)面了,互相介紹握手。一次訪問(wèn)就愉快的完成了。

  • 讓訪問(wèn)者調(diào)用指定的元素。這里需要注意的,訪問(wèn)者調(diào)用元素的行為一般是固定的,很少會(huì)改變的。也就是VisitConcreteElementA()、VisitConcreteElementB()這兩個(gè)方法。也就是定義對(duì)象結(jié)構(gòu)的類(lèi)很少改變,但經(jīng)常需要在此結(jié)構(gòu)上定義新的操作時(shí),會(huì)使用訪問(wèn)者模式

  • 需要對(duì)一個(gè)對(duì)象結(jié)構(gòu)中的對(duì)象進(jìn)行很多不同的并且不相關(guān)的操作,而你想避免讓這些操作“污染”這些對(duì)象的類(lèi)時(shí),適用于訪問(wèn)者模式

  • 訪問(wèn)者模式適合數(shù)據(jù)結(jié)構(gòu)不變化的情況。所以,它是一種平常你用不上,但一旦需要的時(shí)候就只能用這種模式的模式。GoF:“大多時(shí)候你并不需要訪問(wèn)者模式,但當(dāng)一旦你需要訪問(wèn)者模式時(shí),那就是真的需要它了”。因?yàn)楹苌儆袛?shù)據(jù)結(jié)構(gòu)不發(fā)生變化的情況

  • 訪問(wèn)者模式的一些優(yōu)缺點(diǎn):易于增加新的操作;集中相關(guān)的操作而分離無(wú)關(guān)的操作;增加新的ConcreteElement類(lèi)很困難;通過(guò)類(lèi)層次進(jìn)行訪問(wèn);累積狀態(tài);破壞封裝

我們公司的賬務(wù),只有收入和支出兩項(xiàng)(Element),但是不同的部門(mén)(Visitor)訪問(wèn)的時(shí)候會(huì)給出不同的內(nèi)容。比如我查看的時(shí)候只需要查看每月或每季度的匯總數(shù)據(jù)即可,財(cái)務(wù)總監(jiān)則需要詳細(xì)的收支記錄,而會(huì)計(jì)在做賬時(shí)更是需要完整的明細(xì)??梢?jiàn),公司的運(yùn)營(yíng)還真的是需要非常廣泛的知識(shí)的,不僅是管理能力,賬務(wù)知識(shí)也是必要了解的內(nèi)容??!

完整代碼:https://github.com/zhangyue0503/designpatterns-php/blob/master/23.visitor/source/visitor.php

實(shí)例

最后一個(gè)模式的例子還是回到我們的信息發(fā)送上來(lái)。同樣的還是多個(gè)服務(wù)商,它們作為訪問(wèn)者需要去使用各自的短信發(fā)送及APP推送接口。這時(shí),就可以使用訪問(wèn)者模式來(lái)進(jìn)行操作,實(shí)現(xiàn)這些訪問(wèn)者的全部操作。

訪問(wèn)者模式信息發(fā)送

PHP中怎么實(shí)現(xiàn)訪問(wèn)者模式

完整源碼: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 '阿里云發(fā)送短信!', PHP_EOL;
    }
    public function PushMsg(PushMessage $p)
    {
        echo '阿里云推送信息!', PHP_EOL;
    }
}

class JiGuang implements ServiceVisitor
{
    public function SendMsg(SendMessage $s)
    {
        echo '極光發(fā)送短信!', 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 '推送腳本啟動(dòng):';
        $v->PushMsg($this);
    }
}

class SendMessage implements Message
{
    public function Msg(ServiceVisitor $v)
    {
        echo '短信腳本啟動(dòng):';
        $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);

看完上述內(nèi)容,你們掌握PHP中怎么實(shí)現(xiàn)訪問(wèn)者模式的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

php
AI