看了別人文章恍然大悟系列之代理模式

一、代理模式介紹

代理模式是一種非常好理解的一種設計模式, 生活中處處都有代理 :

  • 王寶強作為一個明星,不可能什麼事都由他自己幹(約電視劇、排期之類的),於是他請了經紀人

  • 去醫院掛號很麻煩怎麼辦?找黃牛幫我們掛號

  • 王者榮耀技術水平不夠,想要上分怎麼辦?請遊戲代練

  • 寫點不正經的代碼被警察捉走了怎麼辦?請律師幫我們打官司

無論是經紀人、黃牛、遊戲代練、律師他們都是 得幫我們幹活 。但是他們 不能一手包辦 的,僅僅在“我”的基礎上處理一些雜碎的東西(我們不願意幹、或者幹不了的東西)。

  • 導演找了黃寶強的經紀人 讓王寶強去拍電影 !

  • 黃牛去排隊 讓我們能掛上號 !

  • 律師幫我處理法律上的問題,如果打官司失敗, 牢還是由我來坐 !

再舉個例子:

  • 現在我是一個網紅,擁有很多粉絲。粉絲希望我天天寫代碼給他們看,那我肯定不能天天寫代碼啊,我豈不是很忙....於是乎,我就去找了個經紀人。這個經紀人就代表了我。當 忠實粉絲想要我寫代碼的時候,應該是先找經紀人,告訴經紀人想讓我寫代碼。

  • 十年過去了,我越來越紅了, 頭髮也越來越少 。不是粉絲想要我寫代碼,我就寫了。我要收費了。但是呢,作為一個公眾人物,不可能是我自己說:我要收10000萬,我才會去寫代碼。於是這就讓經紀人對粉絲說:只有10000萬,我才會寫代碼。

  • 無論外界是想要我幹什麼,都要經過我的經紀人。我的經紀人也會在其中考慮收費、推脫它們的請求。

  • 經紀人就是代理,實際寫代碼的還是我

所以說代理模式就是: 當前對象不願意乾的,沒法乾的東西委託給別的對象來做 ,我只要做好本分的東西就好了!

二、用代碼描述代理模式(靜態代理)

這裡有一個程序員接口,他們每天就是寫代碼

看了別人文章恍然大悟系列之代理模式

看了別人文章恍然大悟系列之代理模式

此時Java3y已經是一個網紅了,他不想枯燥地寫代碼。他在想:“在寫代碼時能賺錢就好咯,有人給我錢,我才寫代碼”。 但是 ,Java3y的文筆太爛了,一旦有什麼冬瓜豆腐,分分鐘變成過氣網紅,這是Java3y不願意看到的。

而知乎、博客園這種平臺又 不能 自己給自己點贊來吸引流量(--> 當前對象無法做 )

所以Java3y去請了一個 程序員大V(代理) 來實現自己的計劃,這個程序員大V會每次讓Java3y發文章時,就給Java3y點贊、評論、鼓吹這文章好。只要流量有了,錢就到手了。

看了別人文章恍然大悟系列之代理模式

文章(代碼)還是由Java3y來發,但每次發送之後程序員大V都會點贊。

看了別人文章恍然大悟系列之代理模式

看了別人文章恍然大悟系列之代理模式

這樣一來,不明真相的路人就覺得Java3y是真厲害,知識付費。

2.1透明代理(普通代理)

經過一段時間,Java3y嚐到甜頭了,覺得這是一條財路。於是Java3y給足了程序員大V錢, 讓程序員大V只做他的生意 ,不能做其他人的生意(斷了其他人的財路)。

於是乎,程序員大V 只 做Java3y一個人的生意:

看了別人文章恍然大悟系列之代理模式

於是乎,程序員大V想要賺點零花錢的時候直接讓Java3y發文章就好了。

看了別人文章恍然大悟系列之代理模式

此時, 真實對象(Java3y)對外界來說是透明的 。

2.2代理類自定義方法

程序員大V看到Java3y一直順風順水,賺大錢了。覺得是時候要加價了,於是在點贊完畢後就跟Java3y說 每點完一次贊加100塊 !

於是乎,程序員大V就增添了另外一個方法: addMoney()

看了別人文章恍然大悟系列之代理模式

於是乎程序員大V每次都能多100塊:

看了別人文章恍然大悟系列之代理模式

三、動態代理

幾年時間過去了,Java3y靠著程序員的大V點贊還是沒發財(本質上Java3y還沒有乾貨,沒受到大眾的認可)。此時已經有很多人晉升成了程序員大V了,但是之前的那個程序員大V還是一直累加著錢...雖然在開始的時候Java3y嚐到了甜頭,但現在Java3y財政已經匱乏了。

Java3y將自己的失敗認為:一定是那個程序員大V轉門為我點贊被識破了,吃瓜群眾都知道了,他收費又那麼貴。

於是Java3y不請程序員大V了,請水軍來點贊(水軍便宜, 只要能點贊 就行了):

看了別人文章恍然大悟系列之代理模式

每當Java3y發文章的時候,水軍都會點贊。

看了別人文章恍然大悟系列之代理模式

Java3y感嘆:請水軍真是 方便 啊~

3.1動態代理調用過程

我們來看看究竟是怎麼請水軍的:

Java提供了一個Proxy類,調用它的newInstance方法可以生成某個對象的代理對象,該方法需要三個參數:

看了別人文章恍然大悟系列之代理模式

  • 參數一:生成代理對象使用哪個類裝載器【一般我們使用的是被代理類的裝載器】

  • 參數二:生成哪個對象的代理對象,通過接口指定【指定要被代理類的接口】

  • 參數三:生成的代理對象的方法裡幹什麼事【實現handler接口,我們想怎麼實現就怎麼實現】

在編寫動態代理之前,要明確幾個概念:

  • 代理對象擁有目標對象相同的方法【因為參數二指定了對象的接口,代理對象會實現接口的所有方法】

  • 用戶調用代理對象的什麼方法,都是在調用處理器的invoke方法。【被攔截】

  • 使用JDK動態代理必須要有接口【參數二需要接口】

上面也說了:代理對象會實現接口的所有方法,這些實現的方法交由我們的 handler 來處理!

  • 所有通過動態代理 實現的方法全部 通過 invoke() 調用

看了別人文章恍然大悟系列之代理模式

所以 動態代理調用過程 是這樣子的:

看了別人文章恍然大悟系列之代理模式

3.2靜態代理和動態代理的區別

很明顯的是:

  • 靜態代理需要自己寫代理類-->代理類需要實現與目標對象相同的接口

  • 而動態代理不需要自己編寫代理類--->(是動態生成的)

使用靜態代理時:

  • 如果目標對象的接口有 很多方法 的話,那我們還是得一一實現,這樣就會比較麻煩

使用動態代理時:

  • 代理對象的生成,是利用JDKAPI, 動態地在內存中構建代理對象 (需要我們指定創建 代理對象/目標對象 實現的接口的類型),並且會 默認實現接口的全部方法 。


分享到:


相關文章: