欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go設(shè)計模式之代理模式圖文詳解

 更新時間:2023年07月24日 08:31:56   作者:demo007x  
這篇文章將通過圖文講解給大家詳細(xì)的介紹一下Go代理模式,代理模式是一種結(jié)構(gòu)型設(shè)計模式,代理控制著對于原對象的訪問, 并允許在將請求提交給對象前后進(jìn)行一些處理,感興趣的同學(xué)跟著小編一起來看看吧

代理模式

亦稱: Proxy

代理模式是一種結(jié)構(gòu)型設(shè)計模式, 讓你能夠提供對象的替代品或其占位符。 代理控制著對于原對象的訪問, 并允許在將請求提交給對象前后進(jìn)行一些處理。

問題

為什么要控制對于某個對象的訪問呢? 舉個例子: 有這樣一個消耗大量系統(tǒng)資源的巨型對象, 你只是偶爾需要使用它, 并非總是需要。

數(shù)據(jù)庫查詢有可能會非常緩慢。

你可以實(shí)現(xiàn)延遲初始化: 在實(shí)際有需要時再創(chuàng)建該對象。 對象的所有客戶端都要執(zhí)行延遲初始代碼。 不幸的是, 這很可能會帶來很多重復(fù)代碼。

在理想情況下, 我們希望將代碼直接放入對象的類中, 但這并非總是能實(shí)現(xiàn): 比如類可能是第三方封閉庫的一部分。

解決方案

代理模式建議新建一個與原服務(wù)對象接口相同的代理類, 然后更新應(yīng)用以將代理對象傳遞給所有原始對象客戶端。 代理類接收到客戶端請求后會創(chuàng)建實(shí)際的服務(wù)對象, 并將所有工作委派給它。

代理將自己偽裝成數(shù)據(jù)庫對象, 可在客戶端或?qū)嶋H數(shù)據(jù)庫對象不知情的情況下處理延遲初始化和緩存查詢結(jié)果的工作。

這有什么好處呢? 如果需要在類的主要業(yè)務(wù)邏輯前后執(zhí)行一些工作, 你無需修改類就能完成這項(xiàng)工作。 由于代理實(shí)現(xiàn)的接口與原類相同, 因此你可將其傳遞給任何一個使用實(shí)際服務(wù)對象的客戶端。

真實(shí)世界類比

信用卡和現(xiàn)金在支付過程中的用處相同。

信用卡是銀行賬戶的代理, 銀行賬戶則是一大捆現(xiàn)金的代理。 它們都實(shí)現(xiàn)了同樣的接口, 均可用于進(jìn)行支付。 消費(fèi)者會非常滿意, 因?yàn)椴槐仉S身攜帶大量現(xiàn)金; 商店老板同樣會十分高興, 因?yàn)榻灰资杖肽芤噪娮踊姆绞竭M(jìn)入商店的銀行賬戶中, 無需擔(dān)心存款時出現(xiàn)現(xiàn)金丟失或被搶劫的情況。

代理模式結(jié)構(gòu)

  • 服務(wù)接口 (Service Interface) 聲明了服務(wù)接口。 代理必須遵循該接口才能偽裝成服務(wù)對象。

  • 服務(wù) (Service) 類提供了一些實(shí)用的業(yè)務(wù)邏輯。

  • 代理 (Proxy) 類包含一個指向服務(wù)對象的引用成員變量。 代理完成其任務(wù) (例如延遲初始化、 記錄日志、 訪問控制和緩存等) 后會將請求傳遞給服務(wù)對象。

    通常情況下, 代理會對其服務(wù)對象的整個生命周期進(jìn)行管理。

  • 客戶端 (Client) 能通過同一接口與服務(wù)或代理進(jìn)行交互, 所以你可在一切需要服務(wù)對象的代碼中使用代理。

偽代碼

本例演示如何使用代理模式在第三方騰訊視頻 (TencentVideo, 代碼示例中記為 TV) 程序庫中添加延遲初始化和緩存。

使用代理緩沖服務(wù)結(jié)果。

程序庫提供了視頻下載類。 但是該類的效率非常低。 如果客戶端程序多次請求同一視頻, 程序庫會反復(fù)下載該視頻, 而不會將首次下載的文件緩存下來復(fù)用。

代理類實(shí)現(xiàn)和原下載器相同的接口, 并將所有工作委派給原下載器。 不過, 代理類會保存所有的文件下載記錄, 如果程序多次請求同一文件, 它會返回緩存的文件。

// 遠(yuǎn)程服務(wù)接口。
interface ThirdPartyTVLib is
    method listVideos()
    method getVideoInfo(id)
    method downloadVideo(id)
// 服務(wù)連接器的具體實(shí)現(xiàn)。該類的方法可以向騰訊視頻請求信息。請求速度取決于
// 用戶和騰訊視頻的互聯(lián)網(wǎng)連接情況。如果同時發(fā)送大量請求,即使所請求的信息
// 一模一樣,程序的速度依然會減慢。
class ThirdPartyTVClass implements ThirdPartyTVLib is
    method listVideos() is
        // 向騰訊視頻發(fā)送一個 API 請求。
    method getVideoInfo(id) is
        // 獲取某個視頻的元數(shù)據(jù)。
    method downloadVideo(id) is
        // 從騰訊視頻下載一個視頻文件。
// 為了節(jié)省網(wǎng)絡(luò)帶寬,我們可以將請求結(jié)果緩存下來并保存一段時間。但你可能無
// 法直接將這些代碼放入服務(wù)類中。比如該類可能是第三方程序庫的一部分或其簽
// 名是`final(最終)`。因此我們會在一個實(shí)現(xiàn)了服務(wù)類接口的新代理類中放入
// 緩存代碼。當(dāng)代理類接收到真實(shí)請求后,才會將其委派給服務(wù)對象。
class CachedTVClass implements ThirdPartyTVLib is
    private field service: ThirdPartyTVLib
    private field listCache, videoCache
    field needReset
    constructor CachedTVClass(service: ThirdPartyTVLib) is
        this.service = service
    method listVideos() is
        if (listCache == null || needReset)
            listCache = service.listVideos()
        return listCache
    method getVideoInfo(id) is
        if (videoCache == null || needReset)
            videoCache = service.getVideoInfo(id)
        return videoCache
    method downloadVideo(id) is
        if (!downloadExists(id) || needReset)
            service.downloadVideo(id)
// 之前直接與服務(wù)對象交互的 GUI 類不需要改變,前提是它僅通過接口與服務(wù)對
// 象交互。我們可以安全地傳遞一個代理對象來代替真實(shí)服務(wù)對象,因?yàn)樗鼈兌紝?shí)
// 現(xiàn)了相同的接口。
class TVManager is
    protected field service: ThirdPartyTVLib
    constructor TVManager(service: ThirdPartyTVLib) is
        this.service = service
    method renderVideoPage(id) is
        info = service.getVideoInfo(id)
        // 渲染視頻頁面。
    method renderListPanel() is
        list = service.listVideos()
        // 渲染視頻縮略圖列表。
    method reactOnUserInput() is
        renderVideoPage()
        renderListPanel()
// 程序可在運(yùn)行時對代理進(jìn)行配置。
class Application is
    method init() is
        aTVService = new ThirdPartyTVClass()
        aTVProxy = new CachedTVClass(aTVService)
        manager = new TVManager(aTVProxy)
        manager.reactOnUserInput()

代理模式適合應(yīng)用場景

使用代理模式的方式多種多樣, 我們來看看最常見的幾種。

  • 延遲初始化 (虛擬代理)。 如果你有一個偶爾使用的重量級服務(wù)對象, 一直保持該對象運(yùn)行會消耗系統(tǒng)資源時, 可使用代理模式。

  • 你無需在程序啟動時就創(chuàng)建該對象, 可將對象的初始化延遲到真正有需要的時候。

  • 訪問控制 (保護(hù)代理)。 如果你只希望特定客戶端使用服務(wù)對象, 這里的對象可以是操作系統(tǒng)中非常重要的部分, 而客戶端則是各種已啟動的程序 (包括惡意程序), 此時可使用代理模式。

  • 代理可僅在客戶端憑據(jù)滿足要求時將請求傳遞給服務(wù)對象。

  • 本地執(zhí)行遠(yuǎn)程服務(wù) (遠(yuǎn)程代理)。 適用于服務(wù)對象位于遠(yuǎn)程服務(wù)器上的情形。在這種情形中, 代理通過網(wǎng)絡(luò)傳遞客戶端請求, 負(fù)責(zé)處理所有與網(wǎng)絡(luò)相關(guān)的復(fù)雜細(xì)節(jié)。

  • 記錄日志請求 (日志記錄代理)。 適用于當(dāng)你需要保存對于服務(wù)對象的請求歷史記錄時。代理可以在向服務(wù)傳遞請求前進(jìn)行記錄。

  • 緩存請求結(jié)果 (緩存代理)。 適用于需要緩存客戶請求結(jié)果并對緩存生命周期進(jìn)行管理時, 特別是當(dāng)返回結(jié)果的體積非常大時。代理可對重復(fù)請求所需的相同結(jié)果進(jìn)行緩存, 還可使用請求參數(shù)作為索引緩存的鍵值。

  • 智能引用。 可在沒有客戶端使用某個重量級對象時立即銷毀該對象。代理會將所有獲取了指向服務(wù)對象或其結(jié)果的客戶端記錄在案。 代理會時不時地遍歷各個客戶端, 檢查它們是否仍在運(yùn)行。 如果相應(yīng)的客戶端列表為空, 代理就會銷毀該服務(wù)對象, 釋放底層系統(tǒng)資源。

  • 代理還可以記錄客戶端是否修改了服務(wù)對象。 其他客戶端還可以復(fù)用未修改的對象。

實(shí)現(xiàn)方式

  • 如果沒有現(xiàn)成的服務(wù)接口, 你就需要創(chuàng)建一個接口來實(shí)現(xiàn)代理和服務(wù)對象的可交換性。 從服務(wù)類中抽取接口并非總是可行的, 因?yàn)槟阈枰獙Ψ?wù)的所有客戶端進(jìn)行修改, 讓它們使用接口。 備選計劃是將代理作為服務(wù)類的子類, 這樣代理就能繼承服務(wù)的所有接口了。
  • 創(chuàng)建代理類, 其中必須包含一個存儲指向服務(wù)的引用的成員變量。 通常情況下, 代理負(fù)責(zé)創(chuàng)建服務(wù)并對其整個生命周期進(jìn)行管理。 在一些特殊情況下, 客戶端會通過構(gòu)造函數(shù)將服務(wù)傳遞給代理。
  • 根據(jù)需求實(shí)現(xiàn)代理方法。 在大部分情況下, 代理在完成一些任務(wù)后應(yīng)將工作委派給服務(wù)對象。
  • 可以考慮新建一個構(gòu)建方法來判斷客戶端可獲取的是代理還是實(shí)際服務(wù)。 你可以在代理類中創(chuàng)建一個簡單的靜態(tài)方法, 也可以創(chuàng)建一個完整的工廠方法。
  • 可以考慮為服務(wù)對象實(shí)現(xiàn)延遲初始化。

代理模式優(yōu)缺點(diǎn)

  • 你可以在客戶端毫無察覺的情況下控制服務(wù)對象。

  • 如果客戶端對服務(wù)對象的生命周期沒有特殊要求, 你可以對生命周期進(jìn)行管理。

  • 即使服務(wù)對象還未準(zhǔn)備好或不存在, 代理也可以正常工作。

  • 開閉原則。 你可以在不對服務(wù)或客戶端做出修改的情況下創(chuàng)建新代理。

  • 代碼可能會變得復(fù)雜, 因?yàn)樾枰陆ㄔS多類。

  • 服務(wù)響應(yīng)可能會延遲。

代碼示例

Go設(shè)計模式之代理模式講解和代碼示例_Golang_腳本之家 (jb51.net)

到此這篇關(guān)于Go設(shè)計模式之代理模式圖文詳解的文章就介紹到這了,更多相關(guān)Go代理模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang 打印error的堆棧信息操作

    golang 打印error的堆棧信息操作

    這篇文章主要介紹了golang 打印error的堆棧信息操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • golang結(jié)合mysql設(shè)置最大連接數(shù)和最大空閑連接數(shù)

    golang結(jié)合mysql設(shè)置最大連接數(shù)和最大空閑連接數(shù)

    本文介紹golang?中連接MySQL時,如何設(shè)置最大連接數(shù)和最大空閑連接數(shù),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 詳解Golang中字符串的使用

    詳解Golang中字符串的使用

    這篇文章主要為大家詳細(xì)介紹了Golang中字符串的使用,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Golang有一定的幫助,感興趣的小伙伴可以了解一下
    2022-10-10
  • Golang實(shí)現(xiàn)短網(wǎng)址/短鏈服務(wù)的開發(fā)筆記分享

    Golang實(shí)現(xiàn)短網(wǎng)址/短鏈服務(wù)的開發(fā)筆記分享

    這篇文章主要為大家詳細(xì)介紹了如何使用Golang實(shí)現(xiàn)短網(wǎng)址/短鏈服務(wù),文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價值,感興趣的小伙伴可以了解一下
    2023-05-05
  • 淺談Go中數(shù)字轉(zhuǎn)換字符串的正確姿勢

    淺談Go中數(shù)字轉(zhuǎn)換字符串的正確姿勢

    這篇文章主要介紹了淺談Go中數(shù)字轉(zhuǎn)換字符串的正確姿勢,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • 基于Golang實(shí)現(xiàn)內(nèi)存數(shù)據(jù)庫的示例詳解

    基于Golang實(shí)現(xiàn)內(nèi)存數(shù)據(jù)庫的示例詳解

    這篇文章主要為大家詳細(xì)介紹了如何基于Golang實(shí)現(xiàn)內(nèi)存數(shù)據(jù)庫,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,需要的小伙伴可以參考一下
    2023-03-03
  • 深入解析Go語言編程中slice切片結(jié)構(gòu)

    深入解析Go語言編程中slice切片結(jié)構(gòu)

    這篇文章主要介紹了Go語言編程中slice切片結(jié)構(gòu),其中Append方法的用法介紹較為詳細(xì),需要的朋友可以參考下
    2015-10-10
  • golang解析json數(shù)據(jù)的4種方法總結(jié)

    golang解析json數(shù)據(jù)的4種方法總結(jié)

    在日常工作中每一名開發(fā)者,不管是前端還是后端,都經(jīng)常使用 JSON,下面這篇文章主要給大家介紹了關(guān)于golang解析json數(shù)據(jù)的4種方法,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • 淺析Golang中的內(nèi)存逃逸

    淺析Golang中的內(nèi)存逃逸

    內(nèi)存逃逸分析是go的編譯器在編譯期間,根據(jù)變量的類型和作用域,確定變量是堆上還是棧上。本文將通過示例淺析一下Golang中的內(nèi)存逃逸,需要的可以了解一下
    2022-10-10
  • 一文詳解Golang中的errors包

    一文詳解Golang中的errors包

    在 Golang 中,errors 包是用于處理錯誤的標(biāo)準(zhǔn)庫, errors 包提供的功能比較簡單,使用起來非常方便,接下來就具體講解一下 errors 包提供的幾個函數(shù),感興趣的小伙伴跟著小編一起來看看吧
    2023-07-07

最新評論