【設計模式】牛掰格拉斯的代理模式
代理的本質
無論任何時候,只要談到設計模式,大腦中一定要蹦出這四個字“活學活用”。
要想對某個事物做到活學活用,必須要對它足夠了解,甚至要剖析到本質才行。
總是會有些人說,我幹嘛要知道原理,幹嘛要去看原始碼?會用就行了。對於這種情況,我只有五個字相送,“你開心就好”。
不可否認,認識一個陌生事物,大部分情況還是要從定義開始。
代理模式:為某物件提供一種代理以控制對該物件的訪問,從而限制、增強或修改該物件的一些特性。
如果對代理模式本身就很熟悉的人,一眼就明白什麼意思,甚至連程式碼怎麼寫都會浮現在腦海中。
關鍵是對代理模式一點都不熟悉的人,看到定義後絕對一臉懵。下面通過簡單的圖形來揭開迷惑。
沒有使用代理模式,如下圖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的成功,代理貢獻了多少,絕對功不可沒。
仔細體會下“加層”的含義,在程式碼中和生活中,你會發現它真的很牛掰格拉斯。
>>> 玩轉SpringBoot系列文章 <<<
【玩轉SpringBoot】配置檔案yml的正確開啟姿勢
【玩轉SpringBoot】用好條件相關注解,開啟自動配置之門
【玩轉SpringBoot】給自動配置來個整體大揭祕
>>> 品Spring系列文章 <<<
品Spring:帝國的基石
品Spring:bean定義上梁山
品Spring:實現bean定義時採用的“先進生產力”
品Spring:註解終於“成功上位”
品Spring:能工巧匠們對註解的“加持”
品Spring:SpringBoot和Spring到底有沒有本質的不同?
品Spring:負責bean定義註冊的兩個“排頭兵”
品Spring:SpringBoot輕鬆取勝bean定義註冊的“第一階段”
品Spring:SpringBoot發起bean定義註冊的“二次攻堅戰”
品Spring:註解之王@Configuration和它的一眾“小弟們”
品Spring:bean工廠後處理器的呼叫規則
品Spring:詳細解說bean後處理器
品Spring:對@PostConstruct和@PreDestroy註解的處理方法
品Spring:對@Resource註解的處理方法
品Spring:對@Autowired和@Value註解的處理方法
品Spring:真沒想到,三十步才能完成一個bean例項的建立
品Spring:關於@Scheduled定時任務的思考與探索,結果尷尬了
>>> 熱門文章集錦 <<<
畢業10年,我有話說
【面試】我是如何面試別人List相關知識的,深度有點長文
我是如何在畢業不久只用1年就升為開發組長的
爸爸又給Spring MVC生了個弟弟叫Spring WebFlux
【面試】我是如何在面試別人Spring事務時“套路”對方的
【面試】Spring事務面試考點吐血整理(建議珍藏)
【面試】我是如何在面試別人Redis相關知識時“軟懟”他的
【面試】吃透了這些Redis知識點,面試官一定覺得你很NB(乾貨 | 建議珍藏)
【面試】如果你這樣回答“什麼是執行緒安全”,面試官都會對你刮目相看(建議珍藏)
【面試】迄今為止把同步/非同步/阻塞/非阻塞/BIO/NIO/AIO講的這麼清楚的好文章(快快珍藏)
【面試】一篇文章幫你徹底搞清楚“I/O多路複用”和“非同步I/O”的前世今生(深度好文,建議珍藏)
【面試】如果把執行緒當作一個人來對待,所有問題都瞬間明白了
Java多執行緒通關———基礎知識挑戰
相關推薦
【設計模式】牛掰格拉斯的代理模式
代理的本質無論任何時候,只要談到設計模式,大腦中一定要蹦出這四個字“活學活用”。要想對某個事物做到活學活用,必須要對它足夠了解,甚至要剖析到本質才行。總是會有些人說,我幹嘛要知道原理,幹嘛要去看原始碼?會用就行了。對於這種情況,我只有五個字相送,“你開心就好”。
【設計原則】軟體設計模式六大原則---學習
又有一種說法: http://www.cnblogs.com/yuanhailiang/p/9432198.html ———————————————————————————— 原文:https://www.cnblogs.com/zhanghengscnc/p/8299
【java設計模式】之 單例(Singleton)模式
1. 單例模式的定義 單例模式(Singleton Pattern)是一個比較簡單的模式,其原始定義如下:Ensure a class has only one instance, and provide a global point of access
【設計優化】- 正確使用 Value Object 模式
在J2EE 軟體開發中,通常會對系統模組進行分層,如下圖所示: 展示層主要負責資料的展示,業務路基層負責具體的業務邏輯處理,而持久層負責資料庫等持久化操作。 大型系統中,這些層次很有可能會被分離,部署在不同的伺服器上。而在兩個層次之間可能通過遠端呼叫 RMI 等方式進行
【java設計模式】之 建造者(Builder)模式
我們還是舉上一節的例子:生產汽車。上一節我們通過模板方法模式控制汽車跑起來的動作,那麼需求是無止境的,現在如果老闆又增加了額外的需求:汽車啟動、停止、鳴笛引擎聲都由客戶自己控制,他想要什麼順序就什麼順序,那該如何做呢? 1. 汽車無休止的改造
【設計模式】第四篇:建造者模式也沒那麼難
![](//p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3c68df3e1ac44ba68c613b630fa5c43f~tplv-k3u1fbpfcp-zoom-1.image) # 一 引言 說明:如果想要直接閱讀定義等理論內容,可以直接跳轉到第二大點 在生活
【設計思想】依賴註入
構造函數 magic clas 實例 reg 調整 emca sde sta 場景:傳統的思路是應用程序用到一個Foo類,就會創建Foo類並調用Foo類的方法,假如這個方法內需要一個Bar類,就會創建Bar類並調用Bar類的方法,而這個方法內需要一個Bim類,就會創建Bi
【設計開發】 Linux C文件創建Open函數
include == code pan lin his class trunc types.h #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>
【USACO習題】牛的旅行
理解 alt lap line 原來 連通塊 很好 只有一個 ring 這道題在洛谷上的鏈接:https://www.luogu.org/problemnew/show/P1522 真心很無語,怎麽會有這麽奇怪的題。。。呃呃,題解。大家的做法幾乎是一樣的,我都不能理解
【設計經驗】1、如何規範的處理inout信號
spi 輸出 def 出現 inf 結果 中一 就是 rate 在FPGA的設計過程中,有時候會遇到雙向信號(既能作為輸出,也能作為輸入的信號叫雙向信號)。比如,IIC總線中的SDA信號就是一個雙向信號,QSPI Flash的四線操作的時候四根信號線均為雙向信號。在Ve
【容斥】牛客小白月賽5——A
無關(relationship) https://www.nowcoder.com/acm/contest/135/A 題目描述 若一個集合A內所有的元素都不是正整數N的因數,則稱N與集合A無關。 給出一個含有k個元素的集合A={a1,a2,a3,...,
【設計經驗】3、燒錄QSPI Flash以及配置mcs檔案的載入速度與傳輸位寬
一、軟體與硬體平臺 軟體平臺: 作業系統:Windows 7 64-bit
【設計經驗】2、ChipScope使用教程
一、軟體與硬體平臺 軟體平臺: 作業系統:Windows 8.1 開發套件:ISE14.7 硬體平臺: &nbs
【比賽報告】牛客OI周賽1-提高組
比賽連結 A.分組 將認識關係轉化為圖中的邊。dfs這張圖,對每一個沒有被訪問過的點,將它標記為源點的反色,回溯的時候統計每個點有多少同色相鄰點,個數等於2時將其顏色轉換。 #include<cstdio> #include<cstring
【設計經驗】4、SERDES關鍵技術總結
一、SERDES介紹 隨著大資料的興起以及資訊科技的快速發展,資料傳輸對匯流排頻寬的要求越來越高,並行傳輸技術的發展受到了時序同步困難、訊號偏移嚴重,抗干擾能力弱以及設計複雜度高等一系列問題的阻礙。與並行傳輸技術相比,序列傳輸技術的引
【備忘】牛課演算法第四期初級班與進階班視訊
├─初級 │ 初級2.mp4 │ 初級3.mp4 │ 初級4-1.mp4 │ 初級4-2.mp4 │ 初級5.mp4 │ 初級6.mp4 │ 基礎7.mp4 │ 基礎8.mp4 │
【作業系統實驗】python程式碼模擬實現生產者消費者模式
相比C/C++指標的折磨,本人更喜歡python程式碼的簡潔,廢話不多說: from multiprocessing import Process, JoinableQueue import time,
【小菜鳥】本人部落格,沒有任何侵權的想法,僅僅是總結了一些前輩們的經驗,做了一些小筆記發表。 在以往學習過程中,遇到太多太多的小問題,網上都有答案,只不過太多太雜,解決問題的答案也是可遇不可求, 總是事倍功半。特此總結出一些自己的小經驗,希望能夠幫助大家。
小菜鳥 本人部落格,沒有任何侵權的想法,僅僅是總結了一些前輩們的經驗,做了一些小筆記發表。 在以往學習過程中,遇到太多太多的小問題,網上都有答案,只不過太多太雜,解決問題的答案也是可遇不可求, 總是事倍功半。特...
【JavaScript高階】10、物件高階(繼承模式)
一、原型鏈繼承 方式1: 原型鏈繼承 1. 套路 1. 定義父型別建構函式 2. 給父型別的原型新增方法 3. 定義子型別的建構函式 4. 建立父型別的物件賦值給子型別的原型 5. 將子型別原型的構造屬性設定為子型別 6. 給子型別原
【C語言】求一個數的二進位制位模式從左到右翻轉後對應的十進位制值。
用函式unsigned int reverse_bit(unsigned int value)實現想要的功能 value是我們想要求的值。 #include <stdio.h> #include <math.h> unsigned