設計模式:訪問者模式 Visitor

目錄

  • 前言
  • 問題
  • 解決方案
  • 結構
  • 代碼


前言

訪問者是一種行為設計模式,它能將算法與其所作用的對象隔離開來。


問題

假如你的團隊開發了一款能夠使用巨型圖像中地理信息的應用程序。 圖像中的每個節點既能代表復雜實體(例如一座城市), 也能代表更精細的對象(例如工業區和旅游景點等)。如果節點代表的真實對象之間存在公路, 那么這些節點就會相互連接。 在程序內部, 每個節點的類型都由其所屬的類來表示,每個特定的節點則是一個對象。
在這里插入圖片描述
一段時間后, 你接到了實現將圖像導出到 XML 文件中的任務。 這些工作最初看上去非常簡單。 你計劃為每個節點類添加導出函數, 然后遞歸執行圖像中每個節點的導出函數。 解決方案簡單且優雅: 使用多態機制可以讓導出方法的調用代碼不會和具體的節點類相耦合。

但你不太走運,系統架構師拒絕批準對已有節點類進行修改。他認為這些代碼已經是產品了, 不想冒險對其進行修改, 因為修改可能會引入潛在的缺陷。
在這里插入圖片描述
此外,他還質疑在節點類中包含導出 XML 文件的代碼是否有意義。 這些類的主要工作是處理地理數據。 導出 XML 文件的代碼放在這里并不合適。

還有另一個原因, 那就是在此項任務完成后, 營銷部門很有可能會要求程序提供導出其他類型文件的功能, 或者提出其他奇怪的要求。 這樣你很可能會被迫再次修改這些重要但脆弱的類。

解決方案

訪問者模式建議將新行為放入一個名為訪問者的獨立類中,而不是試圖將其整合到已有類中。 現在, 需要執行操作的原始對象將作為參數被傳遞給訪問者中的方法, 讓方法能訪問對象所包含的一切必要數據。

如果現在該操作能在不同類的對象上執行會怎么樣呢? 比如在我們的示例中,各節點類導出 XML 文件的實際實現很可能會稍有不同。 因此, 訪問者類可以定義一組(而不是一個)方法,且每個方法可接收不同類型的參數。

但我們究竟應該如何調用這些方法(尤其是在處理整個圖像方面)呢?這些方法的簽名各不相同,因此我們不能使用多態機制。 為了可以挑選出能夠處理特定對象的訪問者方法,我們需要對它的類進行檢查。這是不是聽上去像個噩夢呢?

你可能會問, 我們為什么不使用方法重載呢? 就是使用相同的方法名稱,但它們的參數不同。不幸的是,即使我們的編程語言(例如 Java 和 C#) 支持重載也不行。 由于我們無法提前知曉節點對象所屬的類, 所以重載機制無法執行正確的方法。方法會將 節點 基類作為輸入參數的默認類型。

但是, 訪問者模式可以解決這個問題。 它使用了一種名為雙分派的技巧,不使用累贅的條件語句也可下執行正確的方法。與其讓客戶端來選擇調用正確版本的方法, 不如將選擇權委派給作為參數傳遞給訪問者的對象。 由于該對象知曉其自身的類, 因此能更自然地在訪問者中選出正確的方法。 它們會“接收”一個訪問者并告訴其應執行的訪問者方法。

我承認最終還是修改了節點類, 但畢竟改動很小, 且使得我們能夠在后續進一步添加行為時無需再次修改代碼。

現在, 如果我們抽取出所有訪問者的通用接口, 所有已有的節點都能與我們在程序中引入的任何訪問者交互。 如果需要引入與節點相關的某個行為, 你只需要實現一個新的訪問者類即可。

結構

在這里插入圖片描述

代碼

#include <iostream>
#include <memory>
using namespace std;class FactoryElement;
class HouseElement;
class Visitor{
public:virtual void visit(FactoryElement* facElemPtr)=0;virtual void visit(HouseElement* houElemPtr)=0;virtual ~Visitor(){}
};class Element{
public:virtual void accept(shared_ptr<Visitor> v)=0;virtual ~Element(){}
};
class FactoryElement:public Element{
public:void accept(shared_ptr<Visitor> v) override{v->visit(this);}void featureFac(){cout<<"這是工廠區"<<endl;}
};
class HouseElement:public Element{
public:void accept(shared_ptr<Visitor> v) override{v->visit(this);}void featureHou(){cout<<"這是居民區"<<endl;}
};class XmlVisitor:public Visitor{
public:void visit(FactoryElement* facElemPtr) override{facElemPtr->featureFac();cout<<"導出為xml文件"<<endl;} void visit(HouseElement* houElemPtr) override{houElemPtr->featureHou();cout<<"導出為xml文件"<<endl;} 
};
class JsonVisitor:public Visitor{
public:void visit(FactoryElement* facElemPtr) override{facElemPtr->featureFac();cout<<"導出為json文件"<<endl;} void visit(HouseElement* houElemPtr) override{houElemPtr->featureHou();cout<<"導出為json文件"<<endl;} 
};int main(){auto xmlVisitor=make_shared<XmlVisitor>();auto jsonVisitor=make_shared<JsonVisitor>();auto facElem = make_unique<FactoryElement>();auto houElem = make_unique<HouseElement>();facElem->accept(xmlVisitor);houElem->accept(xmlVisitor);facElem->accept(jsonVisitor);houElem->accept(jsonVisitor);return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/91537.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/91537.shtml
英文地址,請注明出處:http://en.pswp.cn/web/91537.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

OpenCV 學習探秘之四:從角點檢測,SIFT/SURF/ORB特征提取,目標檢測與識別,Haar級聯分類人臉檢測,再到機器學習等接口的全面實戰應用與解析

書接上回&#xff0c;前面介紹了一些基本應用&#xff0c;本篇則著重介紹一些比較復雜的應用。 附&#xff1a;本文所用例子中使用的Opencv庫OpenCV4.5.4版本編譯好的庫 五、特征提取與描述 5.1 角點檢測&#xff1a;Harris 角點和 Shi-Tomasi 角點 5.1.1 Harris 角點檢測&a…

《秋招在即!Redis數據類型面試題解析》

博客主頁&#xff1a;天天困啊系列專欄&#xff1a;面試題關注博主&#xff0c;后期持續更新系列文章如果有錯誤感謝請大家批評指出&#xff0c;及時修改感謝大家點贊&#x1f44d;收藏?評論? Redis中常見的基礎數據結構總共五種&#xff1a;這五種類型分別為String&#xff…

政務網站內容檢測系統對錯敏信息有什么作用

政務網站內容檢測系統在錯敏信息管理中發揮著重要作用&#xff0c;能夠有效提升政府網站的信息安全性與合規性。以下從錯敏信息的作用及蟻巡政務信息巡查系統的功能特點兩方面進行說明。一、政務網站內容檢測系統對錯敏信息的作用1、實時監測與識別內容檢測系統通過智能化技術對…

Tower of Hanoi 漢諾塔

題目描述The Tower of Hanoi game consists of three stacks (left, middle and right) and n round disks of different sizes. Initially, the left stack has all the disks, in increasing order of size from top to bottom. The goal is to move all the disks to the r…

在 Docker 中啟動 Nginx 并掛載配置文件到宿主機目錄

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 在 Docker 中啟動 Nginx 并掛載配置文件到宿主機目錄前言一、創建宿主機目錄存放 Nginx 配置1.1 在宿主機&#xff08;如 Windows 或 Linux&#xff09;上創建目錄&#xff0…

認識ansible(入門)

什么是ansible&#xff1f;Ansible是一款自動化運維工具&#xff0c;基于Python開發&#xff0c;集合了眾多運維工具&#xff08;puppet、cfengine、chef、func、fabric&#xff09;的優點&#xff0c;實現了批量系統配置、批量程序部署、批量運行命令等功能。Ansible是基于模塊…

Apache Ignite 關于 **Executor Service(執行器服務)** 的介紹

這段內容是 Apache Ignite 關于 Executor Service&#xff08;執行器服務&#xff09; 的介紹。我們可以把它理解為&#xff1a;一個分布式的“線程池”&#xff0c;可以把任務分發到集群中的多個節點上去執行。 下面我用通俗易懂的方式幫你徹底理解這個概念。&#x1f310; 什…

應用Builder模式在C++中進行復雜對象構建

引言 在軟件開發中&#xff0c;構建復雜對象時常常會遇到構造函數或setter方法過于復雜的情況。Builder模式作為一種創建型設計模式&#xff0c;能夠有效地解決這一問題。Guoyao 創建的勇勇(YongYong)角色&#xff0c;通過Builder模式實現了對復雜對象的構建過程與表示的分離&a…

gradio作為原型工具

存在的問題&#xff0c;頁面的展示和value不是同一個值的問題&#xff0c;比如說選中了北京&#xff0c;但實際上后端想要的是110000地區碼。 在實際開發中&#xff0c;前端展示給用戶的是可讀的地區名稱&#xff08;如“北京”&#xff09;&#xff0c;而背后處理時通常需要的…

計算聲子譜

準備的還是vasp的必備文件&#xff1a;POSCAR POTCAR KPOINTS&#xff0c;剩下需要的INCAR、band文件下面代碼可以生成&#xff1a;#!/bin/bash if [ ! -f band.conf ];then cat >>band.conf <<EOF ATOM_NAME Ti Al B DIM 1 1 1 BAND 0.0 0.0 0.0 0.5 -0.5 0.5…

深度學習 目標檢測常見指標和yolov1分析

目錄 一、常見指標 1、IoU 2、Confidence置信度 3、精準度和召回率 4、mAP 5、NMS方法 6、檢測速度 前傳耗時 FPS 7、FLOPs 二、YOLOv1 檢測流程 1、圖像網格劃分 2、類別預測 3、輸出張量 損失函數 優點 缺點 如題&#xff0c;這篇介紹一下目標檢測中常見的…

31. 偽類和偽元素區別

總結 選擇對象不同內容說明偽類作用對象元素的狀態或位置偽元素作用對象元素的一部分內容或虛擬內容是否新增節點均不新增節點常用符號:&#xff08;偽類&#xff09;、::&#xff08;偽元素&#xff09;推薦場景偽類用于交互與狀態控制&#xff1b;偽元素用于樣式修飾與內容插…

ChatGPT、Playground手動模擬Agent摘要緩沖混合記憶功能

01. 摘要緩沖混合記憶 摘要緩沖混合記憶中&#xff0c;所需的模塊有&#xff1a; chat_message_history&#xff1a;存儲歷史消息列表。moving_summary_buffer&#xff1a;移除消息的匯總字符串。summary_llm&#xff1a;生成摘要的 LLM&#xff0c;接收 summary&#xff08;…

全國青少年信息素養大賽(無人飛行器主題賽(星際迷航)游記)

作者 FHD_WOLF 發布時間 2025-07-30 21:31 分類 生活游記 騎你的 白馬啊 行你欲行的路 風吹來 花落涂 點一欉香祈求 ---------萬千花蕊慈母悲哀從考場出來&#xff0c;剩下的只有無盡極樂 考前準備&#xff1a; 1.電腦充電。 &#xff08;這個賽項需要自帶設備&#x…

Kubernetes (K8s) 部署資源的完整配置OceanBase

Kubernetes Deployment 配置&#xff08;oceanbase-deployment.yaml&#xff09; # oceanbase-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata:name: oceanbase-deployment spec:replicas: 1selector:matchLabels:app: oceanbasetemplate:metadata:labels:app…

ACS-電機控制Buffer-任意路徑規劃(PVSPLINE繪制圓形)

該程序是一個雙軸運動&#xff0c;繪制圓形 原始程序&#xff08;可以直接使用&#xff09; GLOBAL INT X1,Y1,ii GLOBAL REAL MY_ARRAY(4)(12) GLOBAL REAL piX1 0; Y1 1 ! Axis assignment pi ACOS(-1) ! Shortcut for generating piii 0 LOOP 12MY_ARRAY(0)(ii) COS(…

MongoDB Change Streams 實時數據變更流處理實戰指南

MongoDB Change Streams 實時數據變更流處理實戰指南 業務場景描述 在大型電商平臺或高并發的在線系統中&#xff0c;業務數據的變更&#xff08;如訂單狀態、庫存變動、用戶行為日志&#xff09;需要實時通知下游系統&#xff0c;以便做流式分析、緩存更新或消息推送。傳統的輪…

TIME WEAVER: A Conditional Time Series Generation Model論文閱讀筆記

TIME WEAVER: A Conditional Time Series Generation Model 摘要 想象一下&#xff0c;根據天氣、電動汽車的存在和位置生成一個城市的電力需求模式&#xff0c;這可以用于在冬季凍結期間進行容量規劃。這樣的真實世界的時間序列通常包含配對的異構上下文元數據&#xff08;天氣…

Day 4-2: PyTorch基礎入門 - 從NumPy到深度學習的橋梁

Day 4-2: PyTorch基礎入門 - 從NumPy到深度學習的橋梁 ?? 核心概念(5分鐘理解) 一句話定義 PyTorch是Facebook開發的深度學習框架,將NumPy的數組計算能力擴展到GPU,并加入了自動微分功能,讓構建和訓練神經網絡變得簡單直觀。 為什么重要 GPU加速:比CPU快10-100倍的矩…

法式基因音響品牌SK(SINGKING AUDIO)如何以硬核科技重塑專業音頻版圖

在專業音響的競技場&#xff0c;當多數品牌還在功率參數上纏斗時&#xff0c;一個流淌著法蘭西血液的品牌——SK&#xff08;SINGKING AUDIO&#xff09;&#xff0c;早已構建起令人仰望的技術巔峰。它完美詮釋了真正的聲學藝術&#xff1a;不是技術的炫耀&#xff0c;而是讓尖…