代理的本質
無論任何時候,只要談到設計模式,大腦中一定要蹦出這四個字“活學活用”,
要想對某個事物做到活學活用,必須要對它足夠了解,甚至要剖析到本質才行,
總是會有些人說,我干嘛要知道原理,干嘛要去看原始碼?會用就行了,對于這種情況,我只有五個字相送,“你開心就好”,
不可否認,認識一個陌生事物,大部分情況還是要從定義開始,
代理模式:為某物件提供一種代理以控制對該物件的訪問,從而限制、增強或修改該物件的一些特性,
如果對代理模式本身就很熟悉的人,一眼就明白什么意思,甚至連代碼怎么寫都會浮現在腦海中,
關鍵是對代理模式一點都不熟悉的人,看到定義后絕對一臉懵,下面通過簡單的圖形來揭開迷惑,
沒有使用代理模式,如下圖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多執行緒通關———基礎知識挑戰
品Spring:帝國的基石
作者是作業超過10年的碼農,現在任架構師,喜歡研究技術,崇尚簡單快樂,追求以通俗易懂的語言解說技術,希望所有的讀者都能看懂并記住,下面是公眾號的二維碼,歡迎關注!
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/8580.html
標籤:設計模式
