行為型模式:訪問者模式

来源:https://www.cnblogs.com/liebrother/archive/2019/04/16/10714875.html
-Advertisement-
Play Games

文章首發: "行為型模式:訪問者模式" 十一大行為型模式之十一:訪問者模式。 簡介 姓名 :訪問者模式 英文名 :Visitor Pattern 價值觀 :來訪者便是客,招待就是 個人介紹 : Represent an operation to be performed on the element ...


文章首發:
行為型模式:訪問者模式

如畫

十一大行為型模式之十一:訪問者模式。

簡介

姓名 :訪問者模式
英文名 :Visitor Pattern
價值觀 :來訪者便是客,招待就是
個人介紹
Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.
封裝一些作用於某種數據結構中的各元素的操作,它可以在不改變數據結構的前提下定義作用於這些元素的新的操作。
(來自《設計模式之禪》)

你要的故事

先聲明一下,下麵故事全瞎編的。。。

我們是否還記得 N 年前反腐開始的時候,有一段時間提倡官員宴請吃飯只能幾菜幾湯,不能超出。我記得那會剛讀大一,軍事理論的老師說到這個問題,也發表了他的一些想法,他覺得這麼做比較刻板。今天的故事就和宴請有關。現在中國企業發展越來越大,在社會中擔任的責任也越來越大,政府也越來越重視企業,官員去參觀企業是常有的事,而企業宴請官員也變得格外的常見。

故事的背景就是企業宴請各級官員。不同級別的官員宴請的菜式就不一樣,每家企業的菜式豐富程度也不一樣。我們這裡的訪問對象就用 Alibaba 和 Tencent 這 2 家公司,而訪問者就用郭嘉領導人和省領導人做舉例。這 2 家公司都跟喜來登酒店合作,Alibaba 合作方案是:宴請省領導人則十菜一湯,宴請郭嘉領導人則十四菜兩湯;Tencent 合作方案是:宴請省領導人則八菜一湯,宴請郭嘉領導人則十六菜兩湯。

下麵看看如何用訪問者模式來實現上面的故事。

首先定義一個抽象類:企業。企業有一個共有的特性就是接受上級領導的訪問。

/**
 * 企業
 */
abstract class Company {

    public abstract void accept(Vistor vistor);

}

上面故事我們舉例了 2 家企業,分別是 Alibaba 和 Tencent,這裡實現這 2 家公司的宴請方案,並實現接待訪問者方法。

Alibaba 宴請郭嘉領導人是十四菜兩湯,宴請省領導是十菜一湯。

/**
 * Alibaba 企業
 */
class AlibabaCompany extends Company {

    @Override
    public void accept(Vistor vistor) {
        vistor.visit(this);
    }

    public String entertainProvincialLeader() {
        return "Alibaba 接待省領導:十菜一湯";
    }

    public String entertainNationalLeader() {
        return "Alibaba 接待郭嘉領導:十四菜兩湯";
    }

}

Tencent 宴請郭嘉領導人是十六菜兩湯,宴請省領導是八菜一湯。

/**
 * Tencent 企業
 */
class TencentCompany extends Company {

    @Override
    public void accept(Vistor vistor) {
        vistor.visit(this);
    }

    public String entertainProvincialLeader() {
        return "Tencent 接待省領導:八菜一湯";
    }

    public String entertainNationalLeader() {
        return "Tencent 接待郭嘉領導:十六菜兩湯";
    }
}

這裡定義訪問者介面,訪問者介面有 2 個方法,分別是訪問 Alibaba 企業和訪問 Tencent 企業。

/**
 * 訪問者介面
 */
interface Vistor {

    void visit(AlibabaCompany alibabaCompany);

    void visit(TencentCompany tencentCompany);

}

上面故事中有 2 個訪問者,一個是郭嘉領導人,另一個是省領導人,因為不同企業對應不同訪問者有不同的宴請方案,所以這裡訪問企業是需要調用對應企業的宴請方式。

省領導人訪問企業時,需要調用企業對省領導人的宴請方案,為entertainProvincialLeader()

/**
 * 省領導訪問
 */
class ProvincialLeaderVistor implements Vistor {

    @Override
    public void visit(AlibabaCompany alibabaCompany) {
        System.out.println(alibabaCompany.entertainProvincialLeader());
    }

    @Override
    public void visit(TencentCompany tencentCompany) {
        System.out.println(tencentCompany.entertainProvincialLeader());
    }
}

郭嘉領導人訪問企業時,需要調用企業對郭嘉領導人的宴請方案,為entertainNationalLeader()

/**
 * 郭嘉領導訪問
 */
class NationalLeaderVistor implements Vistor {

    @Override
    public void visit(AlibabaCompany alibabaCompany) {
        System.out.println(alibabaCompany.entertainNationalLeader());
    }

    @Override
    public void visit(TencentCompany tencentCompany) {
        System.out.println(tencentCompany.entertainNationalLeader());
    }
}

上面是訪問者和被訪問者的代碼,因為企業是在喜來登酒店宴請領導人,所以這裡還需要一個酒店,酒店裡面有企業合作的名單,以及負責宴請各路領導的方法提供。

/**
 * 酒店
 */
class Hotel {
    private List<Company> companies = new ArrayList<>();

    public void entertain(Vistor vistor) {
        for (Company company : companies) {
            company.accept(vistor);
        }
    }

    public void add(Company company) {
        companies.add(company);
    }
}

下麵提供測試代碼,看看運行的結果怎樣。

public class VisitorTest {

    public static void main(String[] args) {
        AlibabaCompany alibabaCompany = new AlibabaCompany();
        TencentCompany tencentCompany = new TencentCompany();
        ProvincialLeaderVistor provincialLeaderVistor = new ProvincialLeaderVistor();
        NationalLeaderVistor nationalLeaderVistor = new NationalLeaderVistor();

        Hotel xilaideng = new Hotel();
        xilaideng.add(alibabaCompany);
        xilaideng.add(tencentCompany);

        xilaideng.entertain(provincialLeaderVistor);
        xilaideng.entertain(nationalLeaderVistor);
    }

}

列印結果:
Alibaba 接待省領導:十菜一湯
Tencent 接待省領導:八菜一湯
Alibaba 接待郭嘉領導:十四菜兩湯
Tencent 接待郭嘉領導:十六菜兩湯

完整的訪問者模式代碼已經呈現,花 1 分鐘思考一番,理解整個代碼後我們來看看下麵的總結。

總結

訪問者模式有比較好的擴展性,看看訪問者代碼,我們如果要新增一個訪問者:市領導人,只需新增市領導人類,然後企業提供招待市領導人的菜式,便可實現。當然也有它不好的地方,就是把被訪問者暴露給訪問者,使得訪問者可以直接瞭解被訪問者的所有東西。明白了優缺點,才能更好的在實際中運用,一般訪問者模式運用於要求遍歷多個不同的對象的場景。

推薦閱讀

行為型模式:解釋器模式

行為型模式:觀察者模式

行為型模式:迭代器模式

設計模式系列文章持續更新中,歡迎關註公眾號 LieBrother,一起交流學習。
公眾號後臺回覆『大禮包』獲取 Java、Python、IOS 等教程
加個人微信備註『教程』獲取架構師、機器學習等教程

LieBrother


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 下麵是五個正則合到一起的一個正則表達式 this.options.formData[8].value = value.replace(/[^\d.]/g, '').replace(/\.{2,}/g, '.').replace('.', '$#$').replace(/\./g, '').repla ...
  • 1.標簽選擇器 div{} 2.類選擇器 .one class="one" 3.id選擇器(定義+調用) #one{} id="one" 4.通配符選擇器 *{} 5.後代選擇器 .one a {} 6.子代選擇器 .one>a{} 7.交集選擇器 p.one {} 8.並集選擇器 .one,.tw ...
  • 1.變數 var num=10; var num1,num2,num3; num1=10; num2=20; num3=30; var num1=10,num2=20,num3=30; 註意點: console.log(a); //報錯 var b; console.log(b); //undefi ...
  • table 表頭有時候需要加一些小樣式比如 必填項 這是我項目中遇到的需求 比例,產品, 部門為必填項,這個時候就需要在表頭加個紅色小星星。 首先在table中綁定:header-cell-class-name="must"事件 然後methods中寫must事件如下 must(obj) { if ...
  • 瀏覽器F5刷新的時候有一個刷新執行之前的事件,beforeunload 事件,這個事件可以提示用戶在刷新頁面之前有一個提示。 下麵是beforeunload的用法: 首先在methods中定義beforeunload事件 beforeunloadHandler(e) { // e.preventDe ...
  • 最近看了 "Dan Abramov" 的一些 "博客" ,學到了一些React的一些有趣的知識。決定結合自己的理解總結下。這些內容可能對你實際開發並沒有什麼幫助,不過這可以讓你瞭解到更多React底層實現的內容以及為什麼要怎樣實現。可以讓你跟別人有更多的談資,當然,也可以在某些場合裝一下逼。那麼接下 ...
  • 一、請求後端的JSON數據 JSON是前後端通信的交互格式,JSON(JavaScript Object Notation, JS 對象標記) 是一種輕量級的數據交換格式。 JSON是互聯網各個後臺與前代溝通必備格式,取代了原來的XML。 XML數據格式特別“噁心”,現在市場上99%以上的數據格式都 ...
  • 一、資料庫基礎 1.1什麼是資料庫? 什麼是資料庫? 答:就是一個很大的一個文件,只不過這個文件可以通過一些‘命令’操作數據; 增、刪、改、查數據; 資料庫等於持久數據和數據操作的一個統稱。 資料庫是按照數據結構來組織、存儲及管理數據的倉庫。 資料庫有哪些? MySQL、SQL server、Ora ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...