簡單說說訪問者模式的由來

在全部設計模式中,訪問者模式算得上比較難理解的一種設計模式。雖然這種模式比較難理解,可是也須要去知道這種模式具體是怎麼回事兒,我將從最簡單的代碼講起,嘗試去說說這種模式的由來。設計模式

先給定一個場景:顧客去商店買物品,購物結束後須要在收銀員進行結帳。this

這裏具體羅列一下幾個關鍵詞:顧客(client)、物品(goods)和收銀員(cashier)設計

因而就有如下代碼:code

class Cashier {
    public function checkGoods(Goods $goods) {
        echo "【Goods】Title: {$goods->title}, price: {$goods->price}";
    }
}

class Goods {
    public $title = '';
    public $price = 0;

    public function __construct($title, $price) {
        $this->title = $title;
        $this->price = $price;
    }
}

/* client */
$pencil = new Goods('鉛筆', 2.5);
$cashier = new Cashier();
$cashier->checkGoods($pencil);

整體解釋:繼承

  1. 顧客購買一支鉛筆
  2. 顧客將鉛筆交給收銀員結帳(checkGoods)

以上沒問題,不少相似的項目也是這樣設計的。宏觀來講 cashier 做爲服務去結帳是沒有問題的,畢竟收銀員就是給客戶結帳的,其實這裏有點相似外觀模式(Facade Pattern)。接口

那麼有沒有辦法換一種思路去設計呢?看下面的代碼:ci

class Cashier {
    public function checkGoods(Goods $goods) {
        echo "【Goods】Title: {$goods->title}, price: {$goods->price}";
    }
}

class Goods {
    public $title = '';
    public $price = 0;

    public function __construct($title, $price) {
        $this->title = $title;
        $this->price = $price;
    }

    public function checkSelf(Cashier $cashier) {
        $cashier->checkGoods($this);
    }
}

$pencil = new Goods('鉛筆', 2.5);
$cashier = new Cashier();
$pencil->checkSelf($cashier);

以上代碼在 Goods 中加了一個 checkSelf 方法用於接收 Cashier 實例,在 checkSelf 的這個方法中,咱們調用了實例的 checkGoods 方法。改寫 client 端的代碼,將不在使用 checkGoods 方法進行檢查,而使用的是 checkSelf 方法將 cashier 傳入 Goods 中。element

比較以上兩段代碼的區別,體會思惟方式,這就是訪問者模式的雛形。it

接下來就是抽象了。把實例抽象化,該用接口的用接口,該用繼承的用繼承。io

如下就是改寫上面的例子

interface IVisitor {
    public function visit(IElement $element);
}

interface IElement {
    public function accept(IVisitor $visitor);
}

class Cashier implements IVisitor {
    public function visit(IElement $element) {
        echo "【Goods】Title: {$element->title}, price: {$element->price}";
    }
}

class Goods implements IElement {
    public $title = '';
    public $price = 0;

    public function __construct($title, $price) {
        $this->title = $title;
        $this->price = $price;
    }

    public function accept(IVisitor $visitor) {
        $visitor->visit($this);
    }
}

$pencil = new Goods('鉛筆', 2.5);
$cashier = new Cashier();
$pencil->accept($cashier);

這樣看起來是否是可以理解很多呢?

其實設計模式沒那麼複雜,大部分是一種思惟方式的轉變。

相關文章
相關標籤/搜索