設計模式--訪問者模式【行為型模式】

設計模式的分類

我們都知道有 23 種設計模式,這 23 種設計模式可分為如下三類:

  • 創建型模式(5 種):單例模式、工廠方法模式、抽象工廠模式、建造者模式、原型模式。
  • 結構型模式(7 種):適配器模式、裝飾器模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。
  • 行為型模式(11 種):策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。

在這里插入圖片描述

設計模式系列文章傳送門

設計模式的 7 大原則

設計模式–單例模式【創建型模式】

設計模式–工廠方法模式【創建型模式】

設計模式–抽象工廠模式【創建型模式】

設計模式–建造者模式【創建型模式】

設計模式–原型模式【創建型模式】

設計模式–適配器模式【結構型模式】

設計模式–裝飾器模式【結構型模式】

設計模式–代理模式【結構型模式】

設計模式–外觀模式(門面模式)【結構型模式】

設計模式–橋接模式【結構型模式】

設計模式–組合模式【結構型模式】

設計模式–享元模式【結構型模式】

設計模式–策略模式【行為型模式】

設計模式–模板方法模式【行為型模式】

設計模式–觀察者模式【行為型模式】

設計模式–迭代器模式【行為型模式】

設計模式–責任鏈模式【行為型模式】

設計模式–命令模式【行為型模式】

設計模式–備忘錄模式【行為型模式】

設計模式–狀態模式【行為型模式】

什么是訪問者模式

訪問者模式(Visitor Pattern)是一種行為型設計模式,通過定義一個訪問者對象,實現對數據結構中各個元素進行訪問和處理,訪問者模式可以將數據結構與數據操作分離,使得在增加新的操作時,不需要修改現有的數據結構相關的類。

訪問者模式的組成部分

  • 抽象元素:定義一個接收訪問者的接口,接口中定義了一個接受訪問者的方法。
  • 具體元素:實現了抽象元素接口,是數據結構中具體的元素,用于接受具體的訪問并執行相應的操作。
  • 抽象訪問者:定義了對數據結構中各個元素訪問的操作方法。
  • 具體訪問者:實現了訪問者抽象訪問者接口中具體的操作實現,也就是具體的操作邏輯。
  • 對象結構:是一個包含元素角色的容器,并且提供了遍歷元素集合的方法,使得訪問者可以訪問每一個元素,一般是常見的 List、Map 等集合類。

訪問者模式案例演示

訪問者模式模式在生活中其實是有很多場景的,比如我們開一家早餐店,其中粉、面、粥、包子是各種不同的餐食,顧客可以根據自己的喜好選擇餐食,這里的顧客就是訪問者,而不同的食物則可以看做是元素,根據顧客的選擇來提供不同的食物,下面我們使用代碼來演示這個場景。

Food(抽象元素)

Food 食物就是本案例中的抽象元素,定義了一個接受訪問者訪問的方法,代碼如下:

public interface Food {//接受訪問的方法void accept(Customer customer);}

Pink(具體元素)

Pink 粉就是具體食物,也是一種具體的元素,實現了抽象元素 Food 接口,并重寫了訪問方法,將自身傳遞給訪問者,并提供了一個制作粉的方法,代碼如下:

public class Pink implements Food {@Overridepublic void accept(Customer customer) {//將 粉 元素傳遞給訪問者customer.visit(this);}//制作粉public void makePink() {System.out.println("我是一份廣東炒粉...");}}

Noodle(具體元素)

Noodle 面也是具體食物,同樣是一種具體的元素,實現了抽象元素 Food 接口,并重寫了訪問方法,將自身傳遞給訪問者,并提供了一個制作面的方法,代碼如下:

public class Noodle implements Food {@Overridepublic void accept(Customer customer) {customer.visit(this);}//制作面public void makeNoodle() {System.out.println("我是一份重慶小面...");}}

Bun(具體元素)

Bun 包子也具體食物,也是一種具體的元素,實現了抽象元素 Food 接口,并重寫了訪問方法,將自身傳遞給訪問者,并提供了一個制作包子的方法,代碼如下:

public class Bun implements Food {@Overridepublic void accept(Customer customer) {customer.visit(this);}//制作包子public void makeBun() {System.out.println("我是一份上海小籠包...");}}

Customer(訪問者)

Customer 訪問者,在本案例中顧客就是一個訪問者,訪問者中定義了粉、面、包子的訪問方法,代碼如下:

public interface Customer {//粉void visit(Pink pink);//面void visit(Noodle noodle);//包子void visit(Bun bun);
}

SpecificCustomer(具體訪問者)

SpecificCustomer 是一個具體訪問者,重寫了 Customer 中的粉、面、包子的訪問方法,代碼如下:

public class SpecificCustomer implements Customer{@Overridepublic void visit(Pink pink) {System.out.println("后廚,小王要了一份廣東炒粉...安排起來");pink.makePink();}@Overridepublic void visit(Noodle noodle) {System.out.println("后廚,小李要了一份重慶小面...安排起來");noodle.makeNoodle();}@Overridepublic void visit(Bun bun) {System.out.println("后廚,小美要了一份上海小籠包...安排起來");bun.makeBun();}
}

FoodCollection(對象結構)

FoodCollection 就是本案例中的對象結構,FoodCollection 中有一個 List 容器,存儲了 Food 食物,并提供了添加食物和訪問食物的方法,代碼如下:

public class FoodCollection {List<Food> foodList = new ArrayList<>();public void addFood(Food food){foodList.add(food);}public void accept(Customer customer){for (Food food : foodList) {food.accept(customer);}}}

VisitorClient(客戶端代碼)

三位顧客分別要了不同的食物,代碼如下:

public class VisitorClient {public static void main(String[] args) {//對象結構FoodCollection foodCollection = new FoodCollection();//粉--元素Pink pink = new Pink();//面--元素Noodle noodle = new Noodle();//包子--元素Bun bun = new Bun();//添加到數據集合中foodCollection.addFood(pink);foodCollection.addFood(noodle);foodCollection.addFood(bun);//具體訪問者SpecificCustomer customer = new SpecificCustomer();//開始訪問foodCollection.accept(customer);}}

執行結果如下:

后廚,小王要了一份廣東炒粉...安排起來
我是一份廣東炒粉...
后廚,小李要了一份重慶小面...安排起來
我是一份重慶小面...
后廚,小美要了一份上海小籠包...安排起來
我是一份上海小籠包...

執行結果符合預期。

訪問者模式的優缺點

優點:

  • 數據結構和對這些數據結構進行操作的算法(即訪問者)是進行了分離,使得數據結構的維護和操作更加容易,體現了解耦的思想。
  • 符合單一只能原則,每個類的職責明確,使得代碼更加清晰、易于理解和維護,當出現問題時,能夠更容易地定位到問題所在的類,提高了代碼的可維護性。
  • 代碼復用性較好,通過訪問者來定義所有數據結構的通用功能,在一定程度上提到了代碼的復用。

缺點:

  • 增加新的數據結構困難,每增加一個新的元素,都需要修改訪問者代碼,增加相對應的操作,違反了開閉原則。
  • 在有較多元素的場景的時候,訪問者類會比較復雜,大量的元素的操作會導致訪問者類變的異常復雜。

訪問者模式的使用場景

  • 需要對一個復雜的數據結構進行操作,且這些操作可能需要根據不同的元素類型進行不同操作時,可以使用訪問者模式。
  • 需要在不同的數據結構中執行類似的操作,但不希望在數據結構中添加新的方法時,可以使用訪問者模式。

總結:本篇分享了訪問者模式設計模式,感覺訪問者設計模式還是有一點復雜的感覺,它除了元素和訪問者之外還有一個對象結構的概念,我們使用餐廳有有不同餐食的場景演示了訪問者模式,希望可以幫助不太熟悉訪問者模式的朋友加深理解。

如有不正確的地方歡迎各位指出糾正。

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

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

相關文章

前端循環全解析:JS/ES/TS 循環寫法與實戰示例

循環是編程中控制流程的核心工具。本文將詳細介紹 JavaScript、ES6 及 TypeScript 中各種循環的寫法、特性&#xff0c;并通過實際示例幫助你掌握它們的正確使用姿勢。 目錄 傳統三劍客 for 循環 while 循環 do...while 循環 ES6 新特性 forEach for...of for...in 數組…

數據中心儲能蓄電池狀態監測管理系統 組成架構介紹

安科瑞劉鴻鵬 摘要 隨著數據中心對供電可靠性要求的提高&#xff0c;蓄電池儲能系統成為關鍵的后備電源。本文探討了蓄電池監測系統在數據中心儲能系統中的重要性&#xff0c;分析了ABAT系列蓄電池在線監測系統的功能、技術特點及其應用優勢。通過蓄電池監測系統的實施&#…

Mac端homebrew安裝配置

拷打了一下午o3-mini-high&#xff0c;不如這位博主的超強帖子&#xff0c;10分鐘結束戰斗 跟隨該文章即可&#xff0c;2025/2/19親測可行 mac 安裝HomeBrew(100%成功)_mac安裝homebrew-CSDN博客文章瀏覽閱讀10w次&#xff0c;點贊258次&#xff0c;收藏837次。一直覺得自己寫…

機器學習實戰(8):降維技術——主成分分析(PCA)

第8集&#xff1a;降維技術——主成分分析&#xff08;PCA&#xff09; 在機器學習中&#xff0c;降維&#xff08;Dimensionality Reduction&#xff09; 是一種重要的數據處理技術&#xff0c;用于減少特征維度、去除噪聲并提高模型效率。主成分分析&#xff08;Principal C…

windows環境下用docker搭建php開發環境dnmp

安裝WSL WSL即Linux子系統&#xff0c;比虛擬機占用資源少&#xff0c;安裝的前提是系統必須是win10以上。 WSL的安裝比較簡單&#xff0c;網上有很多教程&#xff0c;例如&#xff1a;WSL簡介與安裝流程&#xff08;Windows 下的 Linux 子系統&#xff09;_wsl安裝-CSDN博客&…

Python網絡爬蟲技術詳解文檔

Python網絡爬蟲技術詳解文檔 目錄 網絡爬蟲概述爬蟲核心技術解析常用Python爬蟲庫實戰案例演示反爬蟲機制與應對策略爬蟲法律與道德規范高級爬蟲技術資源推薦與學習路徑1. 網絡爬蟲概述 1.1 什么是網絡爬蟲 網絡爬蟲(Web Crawler)是一種按特定規則自動抓取互聯網信息的程序…

位運算,雙指針,二分,排序算法

文章目錄 位運算二進制中1的個數題解代碼我們需要0題解代碼 排序模版排序1題解代碼模版排序2題解代碼模版排序3題解代碼 雙指針最長連續不重復子序列題解代碼 二分查找題解代碼 位運算 1. bitset< 16 >將十進制數轉為16位的二進制數 int x 25; cout << bitset<…

一周學會Flask3 Python Web開發-redirect重定向

鋒哥原創的Flask3 Python Web開發 Flask3視頻教程&#xff1a; 2025版 Flask3 Python web開發 視頻教程(無廢話版) 玩命更新中~_嗶哩嗶哩_bilibili 前面我們學過渲染到模板頁面&#xff0c;這個其實是一種內部的轉發&#xff0c;瀏覽器地址欄地址沒有變化。如果我們想重定向…

圖片粘貼上傳實現

圖片上傳 html demo 直接粘貼本地運行查看效果即可&#xff0c;有看不懂的直接喂給 deepseek 會解釋的很清晰 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"…

RedisTemplate存儲含有特殊字符解決

ERROR信息: 案發時間: 2025-02-18 01:01 案發現場: UserServiceImpl.java 嫌疑人: stringRedisTemplate.opsForValue().set(SystemConstants.LOGIN_CODE_PREFIX phone, code, Duration.ofMinutes(3L)); // 3分鐘過期作案動機: stringRedisTemplate繼承了Redistemplate 使用的…

Python正則表達式學習

Python正則表達式全攻略 一、正則表達式基礎 1. 什么是正則表達式&#xff1f; 用于描述字符串匹配規則的表達式廣泛應用于文本處理、表單驗證、數據清洗等領域 2. Python中的re模塊 import re3. 基礎語法 字符說明示例.匹配任意字符(除換行)a.c → abc\d數字 [0-9]\d\d …

20250218 隨筆 垂直分庫分表(Vertical Sharding) 和 水平分庫分表(Horizontal Sharding)

垂直分庫分表&#xff08;Vertical Sharding&#xff09; 和 水平分庫分表&#xff08;Horizontal Sharding&#xff09; 是數據庫拆分的兩種策略。它們在大規模數據庫優化、分布式架構設計中至關重要&#xff0c;主要用于 降低單庫壓力、提高查詢效率、支持高并發。 1. 垂直分…

notepad++右鍵菜單不見了

卸載時沒點擊完成&#xff0c;又重新安裝了一個&#xff0c;最終導致了一些bug&#xff0c;導致右鍵沒有notepad菜單。 解決方式&#xff1a; 新建一個register.reg文件&#xff0c;加入以下代碼&#xff0c;然后雙擊執行即可 代碼說明&#xff1a;Open with Notepad 是右…

重定向與文件緩沖機制

目錄 一、重定向的原理與實踐 1. 輸出重定向&#xff1a;讓數據流向新目的地 2. 追加重定向&#xff1a;在文件末尾追加數據 3. 輸入重定向&#xff1a;從指定文件讀取數據 4. 標準輸出流與標準錯誤流的區別 5. 使用 dup2 實現重定向 二、FILE 結構體的奧秘 1. FILE 中的…

DeepSeek 沖擊(含本地化部署實踐)

DeepSeek無疑是春節檔最火爆的話題&#xff0c;上線不足一月&#xff0c;其全球累計下載量已達4000萬&#xff0c;反超ChatGPT成為全球增長最快的AI應用&#xff0c;并且完全開源。那么究竟DeepSeek有什么魔力&#xff0c;能夠讓大家趨之若鶩&#xff0c;他又將怎樣改變世界AI格…

顯微鏡下的人體結構

顯微鏡下的人體結構&#xff0c;看完以后&#xff0c;你還覺得人類是進化而來的嗎&#xff1f;...... 第一張&#xff1a;電子顯微鏡所觀察到的人類血管&#xff0c;可以非常清楚的看到里面的白細胞和紅細胞 第二張&#xff1a;正在分泌耳垢&#xff08;耳屎&#xff09;的耳道…

DApp 開發入門指南

DApp 開發入門指南 &#x1f528; 1. DApp 基礎概念 1.1 什么是 DApp&#xff1f; 去中心化應用&#xff08;DApp&#xff09;是基于區塊鏈的應用程序&#xff0c;特點是&#xff1a; 后端運行在區塊鏈網絡前端可以是任何框架使用智能合約處理業務邏輯數據存儲在區塊鏈上 1…

鴻蒙狀態管理概述 v2

狀態管理v2 概述狀態管理之v2ObservedV2 和 Trace狀態管理V1版本對嵌套類對象屬性變化直接觀測的局限性ObservedV2 和 Trace 使用場景 Local狀態管理V1版本State裝飾器的局限性 Param狀態管理V1版本接受外部傳入的裝飾器的局限性 OnceEventComputedComputed 使用場景 TypePersi…

Git中revert和reset區別?

git revert 和 git reset 都用于撤銷 Git 中的提交&#xff0c;但它們的作用和使用場景不同&#xff1a; git revert: 作用&#xff1a;創建一個新的提交&#xff0c;撤銷指定的提交內容。使用場景&#xff1a;用于“回滾”已推送到遠程倉庫的提交。這種方法不會改變提交歷史&a…

LabVIEW開發中的電機控制與相機像素差

在電機控制系統中&#xff0c;我們需要精確控制電機運動與相機拍攝畫面之間的關系。理想情況下&#xff0c;當電機帶動相機移動同樣的距離時&#xff0c;相機拍攝畫面中兩點之間的像素差應當是一個固定值。然而&#xff0c;在實際應用中&#xff0c;我們發現這一像素差并非固定…