【設計模式】牛掰格拉斯的代理模式

来源:https://www.cnblogs.com/lixinjie/archive/2020/05/25/a-post-about-designpattern-of-proxy.html
-Advertisement-
Play Games

代理的本質無論任何時候,只要談到設計模式,大腦中一定要蹦出這四個字“活學活用”。要想對某個事物做到活學活用,必須要對它足夠瞭解,甚至要剖析到本質才行。總是會有些人說,我幹嘛要知道原理,幹嘛要去看源碼?會用就行了。對於這種情況,我只有五個字相送,“你開心就好”。不可否認,認識一個陌生事物,大部分情況還 ...



代理的本質



無論任何時候,只要談到設計模式,大腦中一定要蹦出這四個字“活學活用”。

要想對某個事物做到活學活用,必須要對它足夠瞭解,甚至要剖析到本質才行。

總是會有些人說,我幹嘛要知道原理,幹嘛要去看源碼?會用就行了。對於這種情況,我只有五個字相送,“你開心就好”。

不可否認,認識一個陌生事物,大部分情況還是要從定義開始。

代理模式為某對象提供一種代理以控制對該對象的訪問,從而限制、增強或修改該對象的一些特性。

如果對代理模式本身就很熟悉的人,一眼就明白什麼意思,甚至連代碼怎麼寫都會浮現在腦海中。

關鍵是對代理模式一點都不熟悉的人,看到定義後絕對一臉懵。下麵通過簡單的圖形來揭開迷惑。

沒有使用代理模式,如下圖01:


”直接訪問“目標”。

使用了代理模式,如下圖02:


”訪問代理代理訪問“目標”。


人群中一定會有兩種聲音:

1)設計模式是很高深莫測的東西,有這麼簡單嗎?

2)這怎麼沒有代碼實現啊?

來聽聽作者的看法:

1)高深莫測和簡單不一定都是對沖的。幸福絕對是高深莫測的,那什麼是幸福呢,最多的答案恐怕就是,“一畝土地兩頭牛,老婆孩子熱炕頭”。

多麼簡單朴實的答案,可惜,包括我在內的很多人都追求不到。主要原因是我們人為(主觀)的把很多事情搞複雜了。下麵這個事情可以說明這一點。

中秋節放假時到附近的一個小景區去看一看,我發現有一種果樹的果子掛滿枝頭,又大又圓,讓人看了之後特別有欲望,甚至垂涎欲滴,可惜沒有一個人去摘。

我的第一反應就是果子肯定不能吃。過了一會兒,終於抑制不住好奇心,就找了一個比較矮的果樹,摸了摸枝頭上的果子。果然硬如磐石。

2)對於一上來就說代碼實現的人,只能認為是你擁有了一把錘子之後,看什麼都像釘子。

代碼實現永遠都是最後一步,但在它之前,要找出問題,分析問題,給出方案,論證方案可行性。如果這些都OK了,代碼就是水到渠成的事了。

記住這句話:

認清原理,搞清本質,永遠都是最重要的,不單單是在寫代碼上,在社會上依然如此。

那代理的本質是什麼呢?就兩個字,“加層”,即增加一(多)層。這就是本質。

像其它的什麼“控制訪問”啦,“增強或修改特性”啦,只不過是這個“層"產生的一些(副)作用罷了。


生活中充滿著代理


雖然大部分人都沒有參與過訴訟,但作為常識我們都知道,當事人可以通過協議把自己的一些權力授權給律師,律師就可以在法庭上行使這些權利,此時律師就是代理。

現在網購已成為生活的一部分,但是收快遞卻比較麻煩,因為通常家中無人。此時菜鳥驛站(或媽媽驛站)出現了,它幫我們簽收和暫存包裹,所以它就是代理。

現在生活壓力大,每個人都要上班,所以中午和下午都沒有時間去接送自己上小學的孩子,此時只能選擇午托,我們交了托費之後就等於給了它授權,它代替我們去接送孩子,可見午托也是代理。

還有各種產品的代理商,有大區代理,省級代理,市級代理,等等。還有就是微商/代購,微商自己沒有貨品,只是發發朋友圈,最終是別人發貨。代購就更直接了,代替你去購買,然後再郵寄給你。

明星藝人都有自己的經紀人,可以替自己接一些活動,討價還價,安排日程等。此時經紀人就是代理。還有大BOSS也會請一到多個秘書,來代替自己做一些事情。

可見,生活中充滿著很多代理,他們以各種各樣的形式存在著,發揮著各種各樣的功能和作用,也確實解決了很多社會和生活的問題。

但從本質來看,代理大都以“層”的形式呈現,站在老闆的前面,替老闆做事情。


和電腦相關的代理


大部分人可能都聽過這樣一句話,凡是遇到不好解決的問題,大都可以通過加一層得到有效的解決。加的這個層很多時候和代理有關。

為了網路安全問題,可以加一層防火牆,防火牆雖然不完全是代理,但卻用到許多代理的理論和技術。

為了擴充本地區域網絡,可以加一層交換機或路由器,它用來代理和轉髮網絡請求。還會有一些附帶的其它功能。

為了平衡多個伺服器的處理能力,我們在前面加一個請求路由層,也就是負載均衡器了,如Nginx,它可以代理請求,並按規則轉發。

再說說CRUD,原來是我們寫代碼直接使用JDBC訪問資料庫,現在我們寫代碼使用的是ORM框架,ORM框架再使用JDBC去訪問資料庫。ORM框架可以看作是JDBC的代理。

我們可以看到,從硬體到中間件,再到程式框架,都有代理的影子。


和編程相關的代理


上面所說的代理,都是廣義的代理,主要側重於角色和功能。

一旦在編程中談到代理,基本就是狹義代理了。除了廣義代理的要求外,還要保持類型的相容和“介面”的一致

說白了就是需要被代理對象的地方,給它一個代理也可以。可以在被代理對象上調用的方法,在代理上也可以調用。

這個要求和代理模式中的要求是一樣的。

如果被代理的對象是一個類。我們用Target表示。

class Target {

    public String getDateTime() {
        return "2019-10-09"
    }

}


為了保持類型相容和介面一致,我們需要生成一個子類。

除此之外還要有被代理的對象,所以還需一個成員變數。

為了添加一些功能,通常需要重寫一些方法。

class Proxy extends Target {

    private Target target;

    @Override
    public String getDateTime() {
        return target.getDateTime() + ", 星期三";
    }

}

這樣就生成了一個代理,在需要Target的地方換成Proxy也沒有問題,而且還會在日期後面加上星期。

如果被代理的對象是一個介面。我們用ITarget表示。

interface ITarget {

    String sayHello(String name);

}

 

class Target implements ITarget {

    @Override
    public String sayHello(String name) {
        return "hello " + name;
    }

}


此時我們只需實現介面即可(當然也可以生成子類),其它的保持不變。

class Proxy implements ITarget {

    private ITarget target;

    @Override
    public String sayHello(String name) {
        return target.sayHello(name) + ", long time no see.";
    }
}

這也是一個代理,同樣可以使用Proxy代替Target,而且在原來問好的基礎上增加了更多的話語。

由於類型相容且介面一致,所以用戶代碼有時也不知道到底是對象本身還是它的代理,不過這通常並不重要。

代理的好處我們已經看到了,但是也有不好的地方,就是要寫代理的代碼,造成代碼量增加。

這個問題已經通過動態代理解決了。在Java里比較有名的動態代理,就是JDK動態代理CGLIB代理。這大家都知道了。

全文總結

代理的本質就是通過加一層來解決問題。類型相容和介面一致只是限制條件而已。

代理有著廣泛的應用,想想Spring的成功,代理貢獻了多少,絕對功不可沒。

仔細體會下“加層”的含義,在代碼中和生活中,你會發現它真的很牛掰格拉斯。

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

-Advertisement-
Play Games
更多相關文章
  • # 概述 - 1.新增的屬性 placeholder Calendar, date, time, email, url, search ContentEditable Draggable Hidden Context-menu Data-Val(自定義屬性) - 2.新增的標簽 語義化標簽(一群類似 ...
  • 因人而異 自學肯定也是可以的,最主要還是要看個人的學習能力,意志力,和自己的決心, 下麵我就說一下,在自學時需要註意的一些誤區和需要掌握哪些技術知識,才能去找工作。 前端自學者存在的學習誤區: 1、所學東西可能已過時 奉為經典的東西可能已經過時,或者已經有了更好的替代者,而你獲取信息的渠道有限,消息 ...
  • 隨著技術以如此快的速度發展,現在我們有必要選擇合適的工具來使用。每個軟體項目都有它需要滿足的多個需求和規範,因此為了滿足這些需求,選擇一種編程語言以允許您以有效的方式開發和管理項目非常重要。 由於有許多種編程語言和框架可供選擇,它們之間的比較已成為必然,因為你需要知道哪一個提供了最好的服務。當涉及到 ...
  • 什麼是NodeJS JS是腳本語言,腳本語言都需要一個解析器才能運行。對於寫在HTML頁面里的JS,瀏覽器充當瞭解析器的角色。而對於需要獨立運行的JS,NodeJS就是一個解析器。 每一種解析器都是一個運行環境,不但允許JS定義各種數據結構,進行各種計算,還允許JS使用運行環境提供的內置對象和方法做 ...
  • 之前一直採用VS進行各種前端後端的開發,隨著項目的需要,正逐步融合純前端的開發模式,開始主要選型為Vue + Element 進行BS前端的開發,後續會進一步整合Vue + AntDesign的界面套件,作為兩種不同界面框架的展現方式。採用Vue + Element 的前端開發和之前的開發模式需要有... ...
  • 從事web前端6年的工作,曾經是信息管理的一名應屆生,由於專業難找工作,掙錢少,當時選擇了轉行學前端開發技術,今天師兄就給大家講一下,作為應屆生,想學前端快點找工作應該如何去學。 對於畢業生來說,最要緊的事情就是快點找到工作。所以你學前端的時候就抓重點來學,因為很多東西,工作上用不到,所以學了也沒必 ...
  • 前提: (1) 相關博文地址: SpringBoot + Vue + ElementUI 實現後臺管理系統模板 -- 前端篇(一):搭建基本環境:https://www.cnblogs.com/l-y-h/p/12930895.html SpringBoot + Vue + ElementUI 實現 ...
  • 迭代器模式是一種使用頻率非常高的設計模式,迭代器用於對一個聚合對象進行遍歷。通過引入迭代器可以將數據的遍歷功能從聚合對象中分離出來,聚合對象只負責存儲數據,聚合對象只負責存儲數據,而遍曆數據由迭代器來完成。 模式動機 一個聚合對象,如一個列表(List)或者一個集合(Set),應該提供一種方法來讓別 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...