<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          深入淺出訪問者模式

          共 6769字,需瀏覽 14分鐘

           ·

          2021-03-18 09:41

          點擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”

          優(yōu)質(zhì)文章,第一時間送達(dá)

            作者 |  huansky

          來源 |  urlify.cn/aEjABf

          訪問者模式,是行為型設(shè)計模式之一。訪問者模式是一種將數(shù)據(jù)操作與數(shù)據(jù)結(jié)構(gòu)分離的設(shè)計模式,它可以算是 23 中設(shè)計模式中最復(fù)雜的一個,但它的使用頻率并不是很高,大多數(shù)情況下,你并不需要使用訪問者模式,但是當(dāng)你一旦需要使用它時,那你就是需要使用它了。

          訪問者模式的基本想法是,軟件系統(tǒng)中擁有一個由許多對象構(gòu)成的、比較穩(wěn)定的對象結(jié)構(gòu),這些對象的類都擁有一個 accept 方法用來接受訪問者對象的訪問。訪問者是一個接口,它擁有一個 visit 方法,這個方法對訪問到的對象結(jié)構(gòu)中不同類型的元素做出不同的處理。在對象結(jié)構(gòu)的一次訪問過程中,我們遍歷整個對象結(jié)構(gòu),對每一個元素都實施 accept 方法,在每一個元素的 accept 方法中會調(diào)用訪問者的 visit 方法,從而使訪問者得以處理對象結(jié)構(gòu)的每一個元素,我們可以針對對象結(jié)構(gòu)設(shè)計不同的訪問者類來完成不同的操作,達(dá)到區(qū)別對待的效果。

          定義

          封裝一些作用于某種數(shù)據(jù)結(jié)構(gòu)中的各元素的操作,它可以在不改變這個數(shù)據(jù)結(jié)構(gòu)的前提下定義作用于這些元素的新的操作。

          可以對定義這么理解:有這么一個操作,它是作用于一些元素之上的,而這些元素屬于某一個對象結(jié)構(gòu)。同時這個操作是在不改變各元素類的前提下,在這個前提下定義新操作是訪問者模式精髓中的精髓。關(guān)鍵代碼是在數(shù)據(jù)基礎(chǔ)類里面有一個方法接受訪問者,將自身引用傳入訪問者。

          訪問者(Visitor)模式是一種對象行為型模式,其主要優(yōu)點如下:

          1. 擴(kuò)展性好。能夠在不修改對象結(jié)構(gòu)中的元素的情況下,為對象結(jié)構(gòu)中的元素添加新的功能。

          2. 復(fù)用性好??梢酝ㄟ^訪問者來定義整個對象結(jié)構(gòu)通用的功能,從而提高系統(tǒng)的復(fù)用程度。

          3. 靈活性好。訪問者模式將數(shù)據(jù)結(jié)構(gòu)與作用于結(jié)構(gòu)上的操作解耦,使得操作集合可相對自由地演化而不影響系統(tǒng)的數(shù)據(jù)結(jié)構(gòu)。

          4. 符合單一職責(zé)原則。訪問者模式把相關(guān)的行為封裝在一起,構(gòu)成一個訪問者,使每一個訪問者的功能都比較單一。

          主要缺點如下:

          1. 增加新的元素類很困難。在訪問者模式中,每增加一個新的元素類,都要在每一個具體訪問者類中增加相應(yīng)的具體操作,這違背了“開閉原則”。

          2. 破壞封裝。訪問者模式中具體元素對訪問者公布細(xì)節(jié),這破壞了對象的封裝性。

          3. 違反了依賴倒置原則。訪問者模式依賴了具體類,而沒有依賴抽象類。

          基本結(jié)構(gòu)

          訪問者(Visitor)模式實現(xiàn)的關(guān)鍵是如何將作用于元素的操作分離出來封裝成獨立的類,其 UML 類圖如下:

          角色介紹

          • Visitor:接口或者抽象類,定義了對每個 Element 訪問的行為,它的參數(shù)就是被訪問的元素,它的方法個數(shù)理論上與元素的個數(shù)是一樣的,因此,訪問者模式要求元素的類型要穩(wěn)定,如果經(jīng)常添加、移除元素類,必然會導(dǎo)致頻繁地修改 Visitor 接口,如果出現(xiàn)這種情況,則說明不適合使用訪問者模式。

          • ConcreteVisitor:具體的訪問者,它需要給出對每一個元素類訪問時所產(chǎn)生的具體行為。

          • Element:元素接口或者抽象類,它定義了一個接受訪問者(accept)的方法,其意義是指每一個元素都要可以被訪問者訪問。

          • ElementA、ElementB:具體的元素類,它提供接受訪問的具體實現(xiàn),而這個具體的實現(xiàn),通常情況下是使用訪問者提供的訪問該元素類的方法。

          • ObjectStructure:定義當(dāng)中所提到的對象結(jié)構(gòu),對象結(jié)構(gòu)是一個抽象表述,它內(nèi)部管理了元素集合,并且可以迭代這些元素提供訪問者訪問。

          模式的實現(xiàn)

          訪問者模式的實現(xiàn)代碼如下:

          package net.biancheng.c.visitor;

          import java.util.*;

          public class VisitorPattern {
              public static void main(String[] args) {
                  ObjectStructure os = new ObjectStructure();
                  os.add(new ConcreteElementA());
                  os.add(new ConcreteElementB());
                  Visitor visitor = new ConcreteVisitorA();
                  os.accept(visitor);
                  System.out.println("------------------------");
                  visitor = new ConcreteVisitorB();
                  os.accept(visitor);
              }
          }

          //抽象訪問者
          interface Visitor {
              void visit(ConcreteElementA element);

              void visit(ConcreteElementB element);
          }

          //具體訪問者A類
          class ConcreteVisitorA implements Visitor {
              public void visit(ConcreteElementA element) {
                  System.out.println("具體訪問者A訪問-->" + element.operationA());
              }

              public void visit(ConcreteElementB element) {
                  System.out.println("具體訪問者A訪問-->" + element.operationB());
              }
          }

          //具體訪問者B類
          class ConcreteVisitorB implements Visitor {
              public void visit(ConcreteElementA element) {
                  System.out.println("具體訪問者B訪問-->" + element.operationA());
              }

              public void visit(ConcreteElementB element) {
                  System.out.println("具體訪問者B訪問-->" + element.operationB());
              }
          }

          //抽象元素類
          interface Element {
              void accept(Visitor visitor);
          }

          //具體元素A類
          class ConcreteElementA implements Element {
              public void accept(Visitor visitor) {
                  visitor.visit(this);
              }

              public String operationA() {
                  return "具體元素A的操作。";
              }
          }

          //具體元素B類
          class ConcreteElementB implements Element {
              public void accept(Visitor visitor) {
                  visitor.visit(this);
              }

              public String operationB() {
                  return "具體元素B的操作。";
              }
          }

          //對象結(jié)構(gòu)角色
          class ObjectStructure {
              private List<Element> list = new ArrayList<Element>();

              public void accept(Visitor visitor) {
                  Iterator<Element> i = list.iterator();
                  while (i.hasNext()) {
                      ((Element) i.next()).accept(visitor);
                  }
              }

              public void add(Element element) {
                  list.add(element);
              }

              public void remove(Element element) {
                  list.remove(element);
              }
          }

          程序的運行結(jié)果如下:

          具體訪問者A訪問-->具體元素A的操作。
          具體訪問者A訪問
          -->具體元素B的操作。
          ------------------------
          具體訪問者B訪問
          -->具體元素A的操作。
          具體訪問者B訪問
          -->具體元素B的操作。

          模式的應(yīng)用場景

          當(dāng)系統(tǒng)中存在類型數(shù)量穩(wěn)定(固定)的一類數(shù)據(jù)結(jié)構(gòu)時,可以使用訪問者模式方便地實現(xiàn)對該類型所有數(shù)據(jù)結(jié)構(gòu)的不同操作,而又不會對數(shù)據(jù)產(chǎn)生任何副作用(臟數(shù)據(jù))。

          簡而言之,就是當(dāng)對集合中的不同類型數(shù)據(jù)(類型數(shù)量穩(wěn)定)進(jìn)行多種操作時,使用訪問者模式。

          通常在以下情況可以考慮使用訪問者(Visitor)模式。

          1. 對象結(jié)構(gòu)相對穩(wěn)定,但其操作算法經(jīng)常變化的程序。

          2. 對象結(jié)構(gòu)中的對象需要提供多種不同且不相關(guān)的操作,而且要避免讓這些操作的變化影響對象的結(jié)構(gòu)。

          3. 對象結(jié)構(gòu)包含很多類型的對象,希望對這些對象實施一些依賴于其具體類型的操作。

          模式的擴(kuò)展

          訪問者(Visitor)模式是使用頻率較高的一種設(shè)計模式,它常常同以下兩種設(shè)計模式聯(lián)用。

          • 與“迭代器模式”聯(lián)用。因為訪問者模式中的“對象結(jié)構(gòu)”是一個包含元素角色的容器,當(dāng)訪問者遍歷容器中的所有元素時,常常要用迭代器。如【例1】中的對象結(jié)構(gòu)是用 List 實現(xiàn)的,它通過 List 對象的 Iterator() 方法獲取迭代器。如果對象結(jié)構(gòu)中的聚合類沒有提供迭代器,也可以用迭代器模式自定義一個。

          • 訪問者(Visitor)模式同“組合模式”聯(lián)用。因為訪問者(Visitor)模式中的“元素對象”可能是葉子對象或者是容器對象,如果元素對象包含容器對象,就必須用到組合模式,其結(jié)構(gòu)圖如下圖 所示。

           

          總結(jié)

          其實很早之前也看過訪問者模式,但是當(dāng)時一直不能理解這個設(shè)計模式的實現(xiàn),感覺就是很難理解。今天在看,其實也沒有那么難,之所以難還是概念理解不夠深入。

          訪問者模式其實關(guān)鍵的就是兩個類:Visitor 和 Element。Element 有個關(guān)鍵的方法 accept 方法,表示接受 Visitor 的訪問;Visitor 有個關(guān)鍵的的方法是 visit() 方法,參數(shù)是 Element,這樣就可以獲取到任何關(guān)于 Element 的信息。然后就可以按照需求隨意組合 Element 提供的信息。

          只要把上面兩個理解清楚了,其他幾個類無非就是接口類,還有個對象結(jié)構(gòu),整個設(shè)計模式的目的就不難理解了。

          最后除了理解設(shè)計模式的目的,還要理解什么情況下去用,這樣的話,你對一個設(shè)計模式思想就基本就掌握了。




          粉絲福利:Java從入門到入土學(xué)習(xí)路線圖

          ??????

          ??長按上方微信二維碼 2 秒


          感謝點贊支持下哈 

          瀏覽 39
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  人妻av中文无码 人妻-X88AⅤ | 青青草在线视频免费播放 | 成人毛片AV无码 | 日本免费黄色电影网站 | 一级A片免费视频 |