<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ## **模式的定義與特點** 訪問者(Visitor)模式的定義:將作用于某種數據結構中的各元素的操作分離出來封裝成獨立的類,使其在不改變數據結構的前提下可以添加作用于這些元素的新的操作,為數據結構中的每個元素提供多種訪問方式。它將對數據的操作與數據結構進行分離,是行為類模式中最復雜的一種模式。 **優點** 1. 擴展性好。能夠在不修改對象結構中的元素的情況下,為對象結構中的元素添加新的功能。 2. 復用性好。可以通過訪問者來定義整個對象結構通用的功能,從而提高系統的復用程度。 3. 靈活性好。訪問者模式將數據結構與作用于結構上的操作解耦,使得操作集合可相對自由地演化而不影響系統的數據結構。 4. 符合單一職責原則。訪問者模式把相關的行為封裝在一起,構成一個訪問者,使每一個訪問者的功能都比較單一。 5. 將相關的事物集中到一個訪問者對象中。 **缺點** 1. 增加新的元素類(新數據結構)很困難。在訪問者模式中,每增加一個新的元素類,都要在每一個具體訪問者類中增加相應的具體操作,這違背了“開閉原則”。 2. 破壞封裝。訪問者模式中具體元素對訪問者公布細節,這破壞了對象的封裝性。 3. 違反了依賴倒置原則。訪問者模式依賴了具體類,而沒有依賴抽象類。 封裝某些用于作用于某種數據結構中各元素的操作,可以在不改變數 據結構的前提下定義作用于這些元素的新操作。如銀行排號機。 ## **應用場景** 如:排隊,排號。 1. 對象結構相對穩定,但其操作算法經常變化的程序。 2. 對象結構中的對象需要提供多種不同且不相關的操作,而且要避免讓這些操作的變化影響對象的結構。 3. 對象結構包含很多類型的對象,希望對這些對象實施一些依賴于其具體類型的操作。 思路:將類看做一個對象結構,然后劃分元素比較元素是否個數穩定 ## **模式的結構** 1. 抽象訪問者(Visitor)角色:定義一個訪問具體元素的接口,為每個具體元素類對應一個訪問操作 visit() ,該操作中的參數類型標識了被訪問的具體元素。 2. 具體訪問者(ConcreteVisitor)角色:實現抽象訪問者角色中聲明的各個訪問操作,確定訪問者訪問一個元素時該做什么。 3. 抽象元素(Element)角色:聲明一個包含接受操作 accept() 的接口,被接受的訪問者對象作為 accept() 方法的參數。 4. 具體元素(ConcreteElement)角色:實現抽象元素角色提供的 accept() 操作,其方法體通常都是 visitor.visit(this) ,另外具體元素中可能還包含本身業務邏輯的相關操作。 5. 對象結構(Object Structure)角色:是一個包含元素角色的容器,提供讓訪問者對象遍歷容器中的所有元素的方法,通常由 List、Set、Map 等聚合類實現。 其結構圖如圖 ![](https://img.kancloud.cn/25/1b/251bb73fa79db4365546555c909ab567_750x665.png) ``` <?php //抽象訪問者 interface Visitor { public function visit(Element $element); } //具體訪問者A類 class ConcreteVisitorA implements Visitor { public function visit(Element $element) { if ($element instanceof ConcreteElementA) { print_r("具體訪問者A訪問-->" . $element->operationA()); } else if ($element instanceof ConcreteElementB) { print_r("具體訪問者A訪問-->" . $element->operationB()); } } } //具體訪問者B類 class ConcreteVisitorB implements Visitor { public function visit(Element $element) { if ($element instanceof ConcreteElementA) { print_r("具體訪問者B訪問-->" . $element->operationA()); } else if ($element instanceof ConcreteElementB) { print_r("具體訪問者B訪問-->" . $element->operationB()); } } } //抽象元素類 interface Element { public function accept(Visitor $visitor); } //具體元素A類 class ConcreteElementA implements Element { public function accept(Visitor $visitor) { $visitor->visit($this); } public function operationA() { return "具體元素A的操作。"; } } //具體元素B類 class ConcreteElementB implements Element { public function accept(Visitor $visitor) { $visitor->visit($this); } public function operationB() { return "具體元素B的操作。"; } } //對象結構角色 class ObjectStructure { private $list = array(); public function accept(Visitor $visitor) { foreach ($this->list as $key => $element) { $element->accept($visitor); } } public function add(Element $element) { $this->list[] = $element; } public function remove(Element $element, $changeIndex = false) { if ($changeIndex === true) { $key = array_search($element, $this->list); if ($key !== false) { array_splice($this->list, $key, 1); } } else { $this->list[$element]; foreach ($this->list as $key => $value) { if ($value === $element) { unset($this->list[$key]); } } } } } class VisitorPattern { public static function main() { //實例化對象結構角色 $os = new ObjectStructure(); $os->add(new ConcreteElementA()); $os->add(new ConcreteElementB()); //實例化具體訪問者A類 $visitor = new ConcreteVisitorA(); $os->accept($visitor); print_r("------------------------"); //實例化具體訪問者B類 $visitor = new ConcreteVisitorB(); $os->accept($visitor); } } VisitorPattern::main(); ``` 簡單例子: ~~~ interface Visitor { // 抽象訪問者角色 public function visitConcreteElementA(ConcreteElementA $elementA); public function visitConcreteElementB(concreteElementB $elementB); } interface Element { // 抽象節點角色 public function accept(Visitor $visitor); } class ConcreteVisitor1 implements Visitor { // 具體的訪問者1 public function visitConcreteElementA(ConcreteElementA $elementA) {} public function visitConcreteElementB(ConcreteElementB $elementB) {} } class ConcreteVisitor2 implements Visitor { // 具體的訪問者2 public function visitConcreteElementA(ConcreteElementA $elementA) {} public function visitConcreteElementB(ConcreteElementB $elementB) {} } class ConcreteElementA implements Element { // 具體元素A private $_name; public function __construct($name) { $this->_name = $name; } public function getName() { return $this->_name; } public function accept(Visitor $visitor) { // 接受訪問者調用它針對該元素的新方法 $visitor->visitConcreteElementA($this); } } class ConcreteElementB implements Element { // 具體元素B private $_name; public function __construct($name) { $this->_name = $name;} public function getName() { return $this->_name; } public function accept(Visitor $visitor) { // 接受訪問者調用它針對該元素的新方法 $visitor->visitConcreteElementB($this); } } class ObjectStructure { // 對象結構 即元素的集合 private $_collection; public function __construct() { $this->_collection = array(); } public function attach(Element $element) { return array_push($this->_collection, $element); } public function detach(Element $element) { $index = array_search($element, $this->_collection); if ($index !== FALSE) { unset($this->_collection[$index]); } return $index; } public function accept(Visitor $visitor) { foreach ($this->_collection as $element) { $element->accept($visitor); } } } // client $elementA = new ConcreteElementA("ElementA"); $elementB = new ConcreteElementB("ElementB"); $elementA2 = new ConcreteElementB("ElementA2"); $visitor1 = new ConcreteVisitor1(); $visitor2 = new ConcreteVisitor2(); $os = new ObjectStructure(); $os->attach($elementA); $os->attach($elementB); $os->attach($elementA2); $os->detach($elementA); $os->accept($visitor1); $os->accept($visitor2); ~~~ 例子: ``` /* 訪問者模式的簡單例子 我們都知道財務都是有賬本的,這個賬本就可以作為一個對象結構,而它其中的元素有兩種,收入和支出,這滿足我們訪問者模式的要求,即元素的個數是穩定的,因為賬本中的元素只能是收入和支出。 而查看賬本的人可能有這樣幾種,比如老板,會計事務所的注會,財務主管,等等。而這些人在看賬本的時候顯然目的和行為是不同的。 首先我們給出單子的接口,它只有一個方法accept。 */ //單個單子的接口(相當于Element) interface Bill { public function accept(AccountBookViewer $viewer); } //其中的方法參數AccountBookViewer是一個賬本訪問者接口,接下來也就是實現類,收入單子和消費單子,或者說收入和支出類。 //消費的單子(支出類) class ConsumeBill implements Bill { private $amount = 0; //支出費用 private $item = ""; //支出項沒有名稱 public function __construct(float $amount, String $item) { $this->amount = $amount; $this->item = $item; } public function accept(AccountBookViewer $viewer) { //$viewer->view($this); $viewer->viewConsume($this); } public function getAmount() { return $this->amount; } public function getItem() { return $this->item; } } //收入單子(收入類) class IncomeBill implements Bill { private $amount = 0; private $item = ""; public function __construct(float $amount, String $item) { $this->amount = $amount; $this->item = $item; } public function accept(AccountBookViewer $viewer) { //$viewer->view($this); $viewer->viewIncome($this); } public function getAmount() { return $this->amount; } public function getItem() { return $this->item; } } //上面最關鍵的還是里面的accept方法,它直接讓訪問者訪問自己,這相當于一次靜態分派(文章最后進行解釋),當然我們也可以不使用重載而直接給方法不同的名稱。 //賬單查看者接口(相當于Visitor) interface AccountBookViewer { //查看消費的單子 public function viewConsume(ConsumeBill $bill); //查看收入的單子 function viewIncome(IncomeBill $bill); } //注冊會計師類,查看賬本的類之一 class CPA implements AccountBookViewer { //注會在看賬本時,如果是支出,則如果支出是工資,則需要看應該交的稅交了沒 public function viewConsume(ConsumeBill $bill) { if ($bill->getItem() === "工資") { print_r("注會查看工資是否交個人所得稅。"); } } //如果是收入,則所有的收入都要交稅 public function viewIncome(IncomeBill $bill) { print_r("注會查看收入交稅了沒。"); } } //老板類,查看賬本的類之一 老板只關心收入和支出的總額,注冊會計師只關注該交稅的是否交稅 class Boss implements AccountBookViewer { private $totalIncome = 0; private $totalConsume = 0; //老板只關注一共花了多少錢以及一共收入多少錢,其余并不關心 public function viewConsume(ConsumeBill $bill) { $this->totalConsume += $bill->getAmount(); } public function viewIncome(IncomeBill $bill) { $this->totalIncome += $bill->getAmount(); } public function getTotalIncome() { print_r("老板查看一共收入多少,數目是:" . $this->totalIncome); return $this->totalIncome; } public function getTotalConsume() { print_r("老板查看一共花費多少,數目是:" . $this->totalConsume); return $this->totalConsume; } } //賬本類(相當于ObjectStruture對象結構) class AccountBook { //單子列表 private $billList = array(); //添加單子 public function addBill(Bill $bill) { $this->billList[] = $bill; } //供賬本的查看者查看賬本 public function show(AccountBookViewer $viewer) { foreach ($this->billList as $key => $bill) { $bill->accept($viewer); } } } //測試客戶端 class Client { public static function main() { //賬本類(相當于ObjectStruture對象結構) $accountBook = new AccountBook(); //添加兩條收入 $accountBook->addBill(new IncomeBill(10000, "賣商品")); $accountBook->addBill(new IncomeBill(12000, "賣廣告位")); //添加兩條支出 $accountBook->addBill(new ConsumeBill(1000, "工資")); $accountBook->addBill(new ConsumeBill(2000, "材料費")); $boss = new Boss(); //賬單查看者接口AccountBookViewer $cpa = new CPA(); //賬單查看者接口AccountBookViewer //兩個訪問者分別訪問賬本 $accountBook->show($cpa); //會計查看賬本 $accountBook->show($boss); //boss查看賬本 $boss->getTotalConsume(); $boss->getTotalIncome(); } } /* 上面的代碼中,可以這么理解,賬本以及賬本中的元素是非常穩定的,這些幾乎不可能改變,而最容易改變的就是訪問者這部分。 訪問者模式最大的優點就是增加訪問者非常容易,我們從代碼上來看,如果要增加一個訪問者,你只需要做一件事即可,那就是寫一個類,實現AccountBookViewer接口,然后就可以直接調用AccountBook的show方法去訪問賬本了。 如果沒使用訪問者模式,一定會增加許多if else,而且每增加一個訪問者,你都需要改你的if else,代碼會顯得非常臃腫,而且非常難以擴展和維護。 */ Client::main(); ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看