PHP設計模式—訪問者模式

 

定義:

訪問者模式(Visitor):表示一個做用於某對象結構中的各元素的操做。它使你能夠在不改變各元素的類的前提下定義做用於這些元素的新操做。算法

 

結構:

  • Visitor:抽象訪問者,爲該對象結構中ConcreteElement的每個類聲明一個Visit操做。
  • ConcreteVisitor:具體訪問者,實現每一個由Visitor聲明的操做。每一個操做實現算法的一部分,而該算法片斷乃是對應於結構中對象的類。
  • Element:抽象類,定義一個Accept操做,它以一個訪問者爲參數。
  • ConcreteElement:具體元素,實現Accept操做。
  • ObjectStructure:對象結構,能枚舉它的元素,能夠提供一個高層的接口以容許訪問者訪問它的元素。
  • Client:客戶端代碼。

 

代碼實例:

/**
 * 抽象訪問者
 * Class VisitorState
 */
abstract class VisitorState
{
    public $state_name;

    /**
     * 獲得男人的結論或反應
     * @param ConcreteElementMan $concreteElementMan
     * @return mixed
     */
    abstract public function getManConclusion(ConcreteElementMan $concreteElementMan);

    /**
     * 獲得女人的結論或反應
     * @param ConcreteElementWoman $concreteElementWoman
     * @return mixed
     */
    abstract public function getWomanConclusion(ConcreteElementWoman $concreteElementWoman);
}


/**
 * 抽象類,定義一個Accept操做
 * Class ElementPerson
 */
abstract class ElementPerson
{
    public $type_name;

    /**
     * 接受
     * @param VisitorState $visitorState
     * @return mixed
     */
    abstract public function accept(VisitorState $visitorState);
}


/**
 * 具體訪問者,成功狀態
 * Class ConcreteVisitorSuccess
 */
class ConcreteVisitorSuccess extends VisitorState
{
    public function __construct()
    {
        $this->state_name = '成功';
    }

    public function getManConclusion(ConcreteElementMan $concreteElementMan)
    {
        // TODO: Implement getManConclusion() method.
        echo "{$concreteElementMan->type_name}:{$this->state_name}時,背後多半有一個偉大的女人。<br/>";
    }

    public function getWomanConclusion(ConcreteElementWoman $concreteElementWoman)
    {
        // TODO: Implement getWomanConclusion() method.
        echo "{$concreteElementWoman->type_name}:{$this->state_name}時,背後大多有一個不成功的男人。<br/>";
    }
}


/**
 * 具體訪問者,失敗狀態
 * Class ConcreteVisitorFailing
 */
class ConcreteVisitorFailing extends VisitorState
{
    public function __construct()
    {
        $this->state_name = '失敗';
    }

    public function getManConclusion(ConcreteElementMan $concreteElementMan)
    {
        // TODO: Implement getManConclusion() method.
        echo "{$concreteElementMan->type_name}:{$this->state_name}時,悶頭喝酒,誰也不用勸。<br/>";
    }

    public function getWomanConclusion(ConcreteElementWoman $concreteElementWoman)
    {
        // TODO: Implement getWomanConclusion() method.
        echo "{$concreteElementWoman->type_name}:{$this->state_name}時,眼淚汪汪,誰也勸不了。<br/>";
    }
}


/**
 * 具體元素,男人
 * Class ConcreteElementMan
 */
class ConcreteElementMan extends ElementPerson
{
    public function __construct()
    {
        $this->type_name = '男人';
    }

    public function accept(VisitorState $visitorState)
    {
        // TODO: Implement accept() method.
        $visitorState->getManConclusion($this);
    }
}


/**
 * 具體元素,女人
 * Class ConcreteElementWoman
 */
class ConcreteElementWoman extends ElementPerson
{
    public function __construct()
    {
        $this->type_name = '女人';
    }

    public function accept(VisitorState $visitorState)
    {
        // TODO: Implement accept() method.
        $visitorState->getWomanConclusion($this);
    }
}


/**
 * 對象結構
 * Class ObjectStructure
 */
class ObjectStructure
{
    public $elements = [];

    /**
     * 添加
     * @param ElementPerson $elementPerson
     */
    public function add(ElementPerson $elementPerson)
    {
        $this->elements[] = $elementPerson;
    }

    /**
     * 移除
     * @param ElementPerson $elementPerson
     */
    public function remove(ElementPerson $elementPerson)
    {
        foreach ($this->elements as $key => $value) {
            if ($value == $elementPerson) {
                unset($this->elements[$key]);
            }
        }
    }

    /**
     * 查看顯示
     * @param VisitorState $visitorState
     */
    public function display(VisitorState $visitorState)
    {
        foreach ($this->elements as $element) {
            $element->accept($visitorState);
        }
    }
}


// 客戶端調用
$objectStructure = new ObjectStructure();
// 添加男人、女人
$objectStructure->add(new ConcreteElementMan());
$objectStructure->add(new ConcreteElementWoman());

// 成功時反應
$success = new ConcreteVisitorSuccess();
$objectStructure->display($success);

// 失敗時反應
$failing = new ConcreteVisitorFailing();
$objectStructure->display($failing);


// 結果
男人:成功時,背後多半有一個偉大的女人。
女人:成功時,背後大多有一個不成功的男人。
男人:失敗時,悶頭喝酒,誰也不用勸。
女人:失敗時,眼淚汪汪,誰也勸不了。

 

 

總結:

  • 訪問者模式適用於數據結構相對穩定的系統,它把數據結構和做用於結構上的操做之間的耦合解脫開,使得操做集合能夠相對自由地演化。
  • 訪問者模式的目的是要把處理從數據結構分離出來。
  • 訪問者模式的優勢就是增長新的操做很容易,由於增長新的操做就意味着增長一個新的訪問者,訪問者模式將有關的行爲集中到一個訪問者對象中。缺點其實也就是使增長新的數據結構變得困難了。
相關文章
相關標籤/搜索