精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

設計模式:訪問者設計模式

冬至子 ? 來源:墨風如雪小站 ? 作者:墨風如雪 ? 2023-06-06 11:25 ? 次閱讀

一、概述

1.1 定義

訪問者設計模式是一種行為型設計模式,用于將算法與對象結構分離。它允許你在不改變對象結構的前提下定義新的操作。

1.2 作用

訪問者模式的作用是在不改變對象結構的前提下定義新的操作。它允許你定義一個新的操作,而無需修改現有的對象結構。在訪問者模式中,我們將操作封裝在訪問者對象中,并在元素對象上調用訪問者對象的方法,從而實現對元素對象的操作。

1.3 適用場景

訪問者模式適用于以下場景:

?對象結構穩定,但是經常需要在此結構上定義新的操作;?需要對復雜對象結構中的對象進行操作,而且這些對象可能具有不同的類型;?需要在不改變對象結構的前提下,為對象結構中的元素對象動態添加新的操作。

二、角色

2.1 抽象訪問者(Visitor)

抽象訪問者(Visitor)定義了訪問者可以訪問的元素對象的接口。它包含了多個 visit() 方法,每個方法對應一個具體元素對象。

publicinterfaceVisitor{
void visit(ConcreteElementA elementA);
void visit(ConcreteElementB elementB);
}

在上述代碼中,我們定義了一個抽象訪問者接口 Visitor,它包含了兩個 visit() 方法,分別對應具體元素對象 ConcreteElementA 和 ConcreteElementB。

2.2 具體訪問者(ConcreteVisitor)

具體訪問者(ConcreteVisitor)實現了抽象訪問者接口,對不同類型的元素對象進行具體的操作。

publicclassConcreteVisitorAimplementsVisitor{
@Override
publicvoid visit(ConcreteElementA elementA){
System.out.println("ConcreteVisitorA visit ConcreteElementA");
}


@Override
publicvoid visit(ConcreteElementB elementB){
System.out.println("ConcreteVisitorA visit ConcreteElementB");
}
}


publicclassConcreteVisitorBimplementsVisitor{
@Override
publicvoid visit(ConcreteElementA elementA){
System.out.println("ConcreteVisitorB visit ConcreteElementA");
}


@Overridepublicvoid visit(ConcreteElementB elementB){
System.out.println("ConcreteVisitorB visit ConcreteElementB");
}
}

在上述代碼中,我們定義了兩個具體訪問者類 ConcreteVisitorA 和 ConcreteVisitorB,它們分別實現了抽象訪問者接口 Visitor,并對不同類型的元素對象進行具體的操作。

2.3 抽象元素(Element)

抽象元素(Element)定義了元素對象的接口,讓訪問者對象可以訪問自己的元素對象。

publicinterfaceElement{
void accept(Visitor visitor);
}

在上述代碼中,我們定義了一個抽象元素接口 Element,它包含了一個 accept() 方法,該方法接收一個訪問者對象作為參數

2.4 具體元素(ConcreteElement)

具體元素(ConcreteElement)實現了抽象元素接口,定義了自己的 accept() 方法,該方法調用訪問者對象的 visit() 方法,并將自身作為參數傳入。

publicclassConcreteElementAimplementsElement{
@Override
publicvoid accept(Visitor visitor){
        visitor.visit(this);
}
}


publicclassConcreteElementBimplementsElement{
@Override
publicvoid accept(Visitor visitor){
        visitor.visit(this);
}
}

在上述代碼中,我們定義了兩個具體元素類 ConcreteElementA 和 ConcreteElementB,它們分別實現了抽象元素接口 Element,并在 accept() 方法中調用訪問者對象的 visit() 方法,并將自身作為參數傳入。

2.5 對象結構(Object Structure)

對象結構(Object Structure)是元素對象的集合,它提供了一個接口,讓訪問者對象可以訪問集合中的元素對象。

publicclassObjectStructure{
privateList< Element > elements =newArrayList<  >();


publicvoid attach(Element element){
        elements.add(element);
}


publicvoid detach(Element element){
        elements.remove(element);
}


publicvoid accept(Visitor visitor){
for(Element element : elements){
            element.accept(visitor);
}
}
}

在上述代碼中,我們定義了一個對象結構類 ObjectStructure,它包含了一個元素對象的集合 elements,提供了 attach() 和 detach() 方法,用于添加和刪除元素對象。它還提供了一個 accept() 方法,該方法遍歷元素對象集合,并調用每個元素對象的accept() 方法,將訪問者對象作為參數傳入。

三、實現步驟

3.1 創建抽象元素類

publicinterfaceElement{
void accept(Visitor visitor);
}

3.2 創建具體元素類

publicclassConcreteElementAimplementsElement{
@Override
publicvoid accept(Visitor visitor){
        visitor.visit(this);
}
}


publicclassConcreteElementBimplementsElement{
@Override
publicvoid accept(Visitor visitor){
        visitor.visit(this);
}
}

3.3 創建抽象訪問者類

publicinterfaceVisitor{
void visit(ConcreteElementA elementA);
void visit(ConcreteElementB elementB);
}

3.4 創建具體訪問者類

publicclassConcreteVisitorAimplementsVisitor{
@Override
publicvoid visit(ConcreteElementA elementA){
System.out.println("ConcreteVisitorA visit ConcreteElementA");
}


@Override
publicvoid visit(ConcreteElementB elementB){
System.out.println("ConcreteVisitorA visit ConcreteElementB");
}
}


publicclassConcreteVisitorBimplementsVisitor{
@Override
publicvoid visit(ConcreteElementA elementA){
System.out.println("ConcreteVisitorB visit ConcreteElementA");
}


@Override
    publicvoid visit(ConcreteElementB elementB){
System.out.println("ConcreteVisitorB visit ConcreteElementB");
}
}

3.5 創建對象結構類

publicclassObjectStructure{
privateList< Element > elements =newArrayList<  >();


publicvoid attach(Element element){
        elements.add(element);
}


publicvoid detach(Element element){
        elements.remove(element);
}


publicvoid accept(Visitor visitor){
for(Element element : elements){
            element.accept(visitor);
}
}
}

3.6 客戶端調用

publicclassClient{
publicstaticvoid main(String[] args){
ObjectStructure objectStructure =newObjectStructure();
        objectStructure.attach(newConcreteElementA());
        objectStructure.attach(newConcreteElementB());


Visitor visitorA =newConcreteVisitorA();
Visitor visitorB =newConcreteVisitorB();


        objectStructure.accept(visitorA);
        objectStructure.accept(visitorB);
}
}

在上述代碼中,我們創建了一個對象結構 objectStructure,并向其中添加了兩個元素對象 ConcreteElementA 和 ConcreteElementB。然后,我們創建了兩個具體訪問者對象 visitorA 和 visitorB,并調用 objectStructure 的 accept() 方法,將這兩個訪問者對象作為參數傳入。在 accept() 方法中,我們遍歷元素對象集合 elements,并依次調用每個元素對象的 accept() 方法,將訪問者對象作為參數傳入。

四、優缺點

4.1 優點

訪問者設計模式的優點包括:

?可以在不改變對象結構的前提下定義新的操作;?可以將代碼的穩定性和易于擴展性相結合;?可以使得增加新的操作變得簡單。

4.2 缺點

訪問者設計模式的缺點包括:

?增加新的元素對象比較困難;?元素對象的訪問者接口必須穩定,否則會導致所有訪問者對象都需要進行修改;?具體元素對象對訪問者對象的訪問是單向的,訪問者對象無法訪問元素對象的其他方法。

五、擴展點

5.1 雙重分派

在訪問者設計模式中,我們可以通過雙重分派來實現不同的操作。雙重分派是指在訪問者對象中定義了多個具體的 visit() 方法,每個方法對應一個具體元素對象,然后在元素對象中調用訪問者對象的 visit() 方法,并將自身作為參數傳入。

雙重分派的實現方式是通過重載 accept() 方法來實現的。具體來說,我們在抽象元素接口 Element 中定義多個 accept() 方法,每個方法對應一個具體訪問者對象,并在具體元素對象中重載這些 accept() 方法,將具體訪問者對象作為參數傳入。

下面是一個雙重分派的示例代碼:

publicinterfaceElement{
void accept(Visitor visitor);
void accept(Visitor visitor,String param);
}


publicclassConcreteElementAimplementsElement{
@Override
publicvoid accept(Visitor visitor){
        visitor.visit(this);
}


@Override
publicvoid accept(Visitor visitor,String param){
        visitor.visit(this, param);
}
}


publicinterfaceVisitor{
void visit(ConcreteElementA elementA);
void visit(ConcreteElementB elementB);
void visit(ConcreteElementA elementA,String param);
}


publicclassConcreteVisitorAimplementsVisitor{
@Override
publicvoid visit(ConcreteElementA elementA){
System.out.println("ConcreteVisitorA visit ConcreteElementA");
}


@Override
publicvoid visit(ConcreteElementB elementB){
System.out.println("ConcreteVisitorA visit ConcreteElementB");
}


@Override
publicvoid visit(ConcreteElementA elementA,String param){
System.out.println("ConcreteVisitorA visit ConcreteElementA with param "+ param);
}
}


publicclassConcreteVisitorBimplementsVisitor{
@Override
publicvoid visit(ConcreteElementA elementA){
System.out.println("ConcreteVisitorB visit ConcreteElementA");
}


@Override
publicvoid visit(ConcreteElementB elementB){
System.out.println("ConcreteVisitorB visit ConcreteElementB");
}


@Override
publicvoid visit(ConcreteElementA elementA,String param){
System.out.println("ConcreteVisitorB visit ConcreteElementA with param "+ param);
}
}


publicclassObjectStructure{
privateList< Element > elements =newArrayList<  >();


publicvoid attach(Element element){
        elements.add(element);
}


publicvoid detach(Element element){
        elements.remove(element);
}


publicvoid accept(Visitor visitor){
for(Element element : elements){
            element.accept(visitor);
}
}


publicvoid accept(Visitor visitor,String param){
for(Element element : elements){
            element.accept(visitor, param);
}
}
}


publicclassClient{
publicstaticvoid main(String[] args){
ObjectStructure objectStructure =newObjectStructure();
        objectStructure.attach(newConcreteElementA());
        objectStructure.attach(newConcreteElementB());


Visitor visitorA =newConcreteVisitorA();
Visitor visitorB =newConcreteVisitorB();


        objectStructure.accept(visitorA);
        objectStructure.accept(visitorB);
        objectStructure.accept(visitorA,"paramA");
        objectStructure.accept(visitorB,"paramB");
}
}

在上述代碼中,我們定義了一個新的 accept() 方法,該方法接收一個額外的參數 param,并在具體元素對象的 accept() 方法中將該參數傳遞給訪問者對象的 visit() 方法。然后,我們創建了兩個具體訪問者對象 visitorA 和 visitorB,并分別調用 objectStructure 的 accept() 方法,將這兩個訪問者對象作為參數傳入,并在第二個 accept() 方法中傳遞了參數 "paramA" 和 "paramB"。在訪問者對象的 visit() 方法中,我們可以根據傳遞的參數進行不同的操作。

雙重分派的優點是可以根據傳遞的參數實現不同的操作,從而增強了訪問者模式的靈活性和擴展性。

然而,雙重分派也有一些缺點。首先,它會導致類的層次結構變得復雜,因為每個具體元素對象都需要實現多個 accept() 方法。其次,雙重分派會增加代碼的復雜性,因為需要在訪問者對象中定義多個具體的 visit() 方法,并在具體元素對象中重載多個 accept() 方法。最后,雙重分派可能會導致代碼的可讀性變差,因為需要理解多個層次的調用關系。

因此,在使用雙重分派時需要謹慎考慮,避免過度使用,以免導致代碼的復雜性和可維護性下降。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Elements
    +關注

    關注

    0

    文章

    6

    瀏覽量

    5302
收藏 人收藏

    評論

    相關推薦

    如何判斷訪問者的瀏覽器是否打開了JAVASCRIPT功能?

    如何判斷訪問者的瀏覽器是否打開了JAVASCRIPT功能?作者:Hunte | 收錄日期 : 2000-08-21   用這段代碼就可以了
    發表于 01-11 09:33

    LabVIEW主/從設計模式和生產/消費設計模式

    點擊學習>>《龍哥手把手教你學LabVIEW視覺設計》視頻教程本教程將介紹 主/從設計模式與生產/消費設計模式(Master/Slave design pattern
    發表于 12-30 14:12

    狀態機模式與生產/消費模式的關系

    原來有些明白,但是現在又有點糊涂了 ,狀態機模式和生產/消費模式之間到底有沒有關系?有的話到底是什么樣子的關系?求大神解釋!!!!!
    發表于 03-04 11:37

    基于觀察模式的屏幕布局控件設計

    觀察模式作為設計模式中行為模式的一種,解決了上述具有一對多依賴關系對象重用問題。文中在分析觀察模式
    發表于 02-13 16:20 ?4次下載
    基于觀察<b class='flag-5'>者</b><b class='flag-5'>模式</b>的屏幕布局控件設計

    Java設計模式(二十一):中介模式

    中介模式(Mediator Pattern) 中介模式(Mediator Pattern): 屬于對象的行為模式。又叫調停
    發表于 01-24 11:28 ?301次閱讀

    配置Nginx訪問日志

    每當處理客戶請求時,Nginx都會在訪問日志中生成一個新記錄。每個事件記錄都包含一個時間戳,并包含有關客戶端和所請求資源的各種信息。訪問日志可以顯示訪問者的位置,訪問者
    的頭像 發表于 05-24 09:59 ?2285次閱讀

    嵌入式軟件設計模式 好文值得收藏

    本文引用自本人公眾號文章: 嵌入式開發中的兩點編程思想 ? C語言也很講究設計模式?一文講透 ? 包含如下: 01)C語言和設計模式(繼承、封裝、多態) ? 02)C語言和設計模式訪問者
    的頭像 發表于 06-20 09:09 ?1936次閱讀

    GoF設計模式訪問者模式

    訪問者模式的目的是,解耦數據結構和算法,使得系統能夠在不改變現有代碼結構的基礎上,為對象新增一種新的操作。
    的頭像 發表于 10-08 11:05 ?668次閱讀

    用C語言編寫建造模式

    建造模式: 也稱生成器模式,是 23 種設計模式中的一種,是一種創建型模式。適用情況:一個對象比較復雜,將一個對象的構建和對象的表示進行分
    發表于 06-05 11:31 ?496次閱讀
    用C語言編寫建造<b class='flag-5'>者</b><b class='flag-5'>模式</b>

    設計模式行為型:訪問者模式

    訪問者模式(Visitor Pattern)中,我們使用了一個訪問者類,它改變了元素類的執行算法。
    的頭像 發表于 06-07 15:11 ?727次閱讀
    設計<b class='flag-5'>模式</b>行為型:<b class='flag-5'>訪問者</b><b class='flag-5'>模式</b>

    設計模式行為型:觀察模式

    定義對象之間的一種一對多依賴關系,使得每一個對象發生狀態的變化時,其相關依賴對象皆得到通知并被自動更新,又稱為發布-訂閱模式、模型-視圖模式、源-監聽器模式或從屬
    的頭像 發表于 06-07 16:56 ?651次閱讀
    設計<b class='flag-5'>模式</b>行為型:觀察<b class='flag-5'>者</b><b class='flag-5'>模式</b>

    設計模式創造性:建造模式

    建造模式(Builder Pattern)使用多個簡單的對象一步一步構建成一個復雜的對象。這種類型的設計模式屬于創建型模式,它提供了一種創建對象的最佳方式。
    的頭像 發表于 06-09 16:25 ?717次閱讀
    設計<b class='flag-5'>模式</b>創造性:建造<b class='flag-5'>者</b><b class='flag-5'>模式</b>

    UVM設計模式訪問者模式

    Visitor Pattern: 允許一個或者多個操作應用到一組對象上,解耦操作和對象本身。換言之,如果component的數據結構是比較穩定的,但其是易于變化的,那么使用訪問者模式是個不錯的選擇。
    的頭像 發表于 08-11 09:28 ?729次閱讀
    UVM設計<b class='flag-5'>模式</b>之<b class='flag-5'>訪問者</b><b class='flag-5'>模式</b>

    設計模式中代理模式的使用場景

    官方定義: 代理模式 (Proxy Pattern) 是一種結構型設計模式,通過代理對象控制對原對象的訪問,并允許在訪問前或訪問后做一些處理
    的頭像 發表于 10-08 14:34 ?983次閱讀
    設計<b class='flag-5'>模式</b>中代理<b class='flag-5'>模式</b>的使用場景

    什么是觀察設計模式?Golang中的觀察模式介紹

    當涉及到訂單處理系統時,觀察設計模式可以用于實現訂單狀態的變化和通知。
    的頭像 發表于 01-08 10:08 ?403次閱讀