真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

給女朋友講解什么是代理模式

前言

只有光頭才能變強(qiáng)

創(chuàng)新互聯(lián)建站主要從事網(wǎng)站設(shè)計(jì)制作、網(wǎng)站制作、網(wǎng)頁(yè)設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)任縣,10余年網(wǎng)站建設(shè)經(jīng)驗(yàn),價(jià)格優(yōu)惠、服務(wù)專業(yè),歡迎來(lái)電咨詢建站服務(wù):13518219792

多線程就先告一段落了,昨天寫完多線程,本來(lái)打算是看IO的知識(shí)點(diǎn)的,后來(lái)看了一下IO的幾種模型,又翻了一下《Java編程思想》。不知道從哪下手~~

在看到FilterInputStreamFilterOutputStream時(shí)看到了之前常聽見的裝飾模式(對(duì)IO一定了解的同學(xué)可能都會(huì)知道那么一句話:在IO用得最多的就是裝飾模式了)!

看到這里你以為我要講裝飾模式了么?不是,今天我們來(lái)講講什么是代理模式(就是這么皮,裝飾模式明天講吧~)。

受知乎@Beautiful Java文章和《設(shè)計(jì)模式之禪》的啟發(fā),我也來(lái)搞一篇腦洞小開的文章..

由標(biāo)題可知,這篇文章是寫給我女朋友看的。自從她知道我開了公眾號(hào)以后就每天看我寫的文章,之前寫點(diǎn)小算法的時(shí)候她覺(jué)得編程還是挺有意思,想去學(xué)學(xué)。可是,從我開始寫Java容器、多線程,她說(shuō)一點(diǎn)都看不懂了。于是乎,現(xiàn)在來(lái)寫點(diǎn)既高大尚、又容易懂的東西。

    GirlFriend girlFriend = new GirlFriend();
   sayingProxy(girlFriend);

那么接下來(lái)就開始吧,如果文章有錯(cuò)誤的地方請(qǐng)大家多多包涵,不吝在評(píng)論區(qū)指正哦~

聲明:本文使用JDK1.8

一、代理模式介紹

代理模式是一種非常好理解的一種設(shè)計(jì)模式,生活中處處都有代理

  • 王寶強(qiáng)作為一個(gè)明星,不可能什么事都由他自己干(約電視劇、排期之類的),于是他請(qǐng)了經(jīng)紀(jì)人

  • 去醫(yī)院掛號(hào)很麻煩怎么辦?找黃牛幫我們掛號(hào)

  • 王者榮耀技術(shù)水平不夠,想要上分怎么辦?請(qǐng)游戲代練

  • 寫點(diǎn)不正經(jīng)的代碼被警察捉走了怎么辦?請(qǐng)律師幫我們打官司

無(wú)論是經(jīng)紀(jì)人、黃牛、游戲代練、律師他們都是得幫我們干活。但是他們不能一手包辦的,僅僅在“我”的基礎(chǔ)上處理一些雜碎的東西(我們不愿意干、或者干不了的東西)。

  • 導(dǎo)演找了黃寶強(qiáng)的經(jīng)紀(jì)人讓王寶強(qiáng)去拍電影!

  • 黃牛去排隊(duì)讓我們能掛上號(hào)!

  • 游戲代練上分是我的微信賬號(hào)

  • 律師幫我處理法律上的問(wèn)題,如果打官司失敗,牢還是由我來(lái)坐!

再舉個(gè)例子:

  • 現(xiàn)在我是一個(gè)網(wǎng)紅,擁有很多粉絲。粉絲希望我天天寫代碼給他們看,那我肯定不能天天寫代碼啊,我豈不是很忙….于是乎,我就去找了個(gè)經(jīng)紀(jì)人。這個(gè)經(jīng)紀(jì)人就代表了我。當(dāng)忠實(shí)粉絲想要我寫代碼的時(shí)候,應(yīng)該是先找經(jīng)紀(jì)人,告訴經(jīng)紀(jì)人想讓我寫代碼。

  • 十年過(guò)去了,我越來(lái)越紅了,頭發(fā)也越來(lái)越少。不是粉絲想要我寫代碼,我就寫了。我要收費(fèi)了。但是呢,作為一個(gè)公眾人物,不可能是我自己說(shuō):我要收10000萬(wàn),我才會(huì)去寫代碼。于是這就讓經(jīng)紀(jì)人對(duì)粉絲說(shuō):只有10000萬(wàn),我才會(huì)寫代碼。

  • 無(wú)論外界是想要我干什么,都要經(jīng)過(guò)我的經(jīng)紀(jì)人。我的經(jīng)紀(jì)人也會(huì)在其中考慮收費(fèi)、推脫它們的請(qǐng)求。

  • 經(jīng)紀(jì)人就是代理,實(shí)際寫代碼的還是我

所以說(shuō)代理模式就是:當(dāng)前對(duì)象不愿意干的,沒(méi)法干的東西委托給別的對(duì)象來(lái)做,我只要做好本分的東西就好了!

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

這里有一個(gè)程序員接口,他們每天就是寫代碼

public interface Programmer{

   // 程序員每天都寫代碼
   void coding();

}

Java3y也是一個(gè)程序員,他也寫代碼(每個(gè)程序員寫的代碼都不一樣,所以分了接口和實(shí)現(xiàn)類)

public class Java3y implements Programmer{

   @Override
   public void coding(){
       System.out.println("Java3y最新文章:......給女朋友講解什么是代理模式.......");
   }
}

此時(shí)Java3y已經(jīng)是一個(gè)網(wǎng)紅了,他不想枯燥地寫代碼。他在想:“在寫代碼時(shí)能賺錢就好咯,有人給我錢,我才寫代碼”。但是,Java3y的文筆太爛了,一旦有什么冬瓜豆腐,分分鐘變成過(guò)氣網(wǎng)紅,這是Java3y不愿意看到的。

而知乎、博客園這種平臺(tái)又不能自己給自己點(diǎn)贊來(lái)吸引流量(-->當(dāng)前對(duì)象無(wú)法做)

所以Java3y去請(qǐng)了一個(gè)程序員大V(代理)來(lái)實(shí)現(xiàn)自己的計(jì)劃,這個(gè)程序員大V會(huì)每次讓Java3y發(fā)文章時(shí),就給Java3y點(diǎn)贊、評(píng)論、鼓吹這文章好。只要流量有了,錢就到手了。

public class ProgrammerBigV implements Programmer{

   // 指定程序員大V要讓誰(shuí)發(fā)文章(先發(fā)文章、后點(diǎn)贊)
   private Java3y java3y ;

   public ProgrammerBigV(Java3y java3y){
       this.java3y = java3y;
   }

   // 程序員大V點(diǎn)贊評(píng)論收藏轉(zhuǎn)發(fā)
   public void upvote(){
       System.out.println("程序員大V點(diǎn)贊評(píng)論收藏轉(zhuǎn)發(fā)!");
   }

   @Override
   public void coding(){

       // 讓Java3y發(fā)文章
       java3y.coding();

       // 程序員大V點(diǎn)贊評(píng)論收藏轉(zhuǎn)發(fā)!
       upvote();
   }
}

文章(代碼)還是由Java3y來(lái)發(fā),但每次發(fā)送之后程序員大V都會(huì)點(diǎn)贊。

public class Main{

   public static void main(String[] args){

       // 想要發(fā)達(dá)的Java3y
       Java3y java3y = new Java3y();

       // 受委托程序員大V
       Programmer programmer = new ProgrammerBigV(java3y);

       // 受委托程序員大V讓Java3y發(fā)文章,大V(自己)來(lái)點(diǎn)贊
       programmer.coding();
   }  
}
給女朋友講解什么是代理模式

這樣一來(lái),不明真相的路人就覺(jué)得Java3y是真厲害,知識(shí)付費(fèi)。

2.1透明代理(普通代理)

經(jīng)過(guò)一段時(shí)間,Java3y嘗到甜頭了,覺(jué)得這是一條財(cái)路。于是Java3y給足了程序員大V錢,讓程序員大V只做他的生意,不能做其他人的生意(斷了其他人的財(cái)路)。

于是乎,程序員大V做Java3y一個(gè)人的生意:

public class ProgrammerBigV implements Programmer{

   // 指定程序員大V要給Java3y點(diǎn)贊
   private Java3y java3y ;

   // 只做Java3y的生意了
   public ProgrammerBigV(){
       this.java3y = new Java3y();
   }

   // 程序員大V點(diǎn)贊評(píng)論收藏轉(zhuǎn)發(fā)
   public void upvote(){
       System.out.println("程序員大V點(diǎn)贊評(píng)論收藏轉(zhuǎn)發(fā)!");
   }

   @Override
   public void coding(){

       // 讓Java3y發(fā)文章了
       java3y.coding();

       // 程序員大V點(diǎn)贊評(píng)論收藏轉(zhuǎn)發(fā)!
       upvote();

   }
}

于是乎,程序員大V想要賺點(diǎn)零花錢的時(shí)候直接讓Java3y發(fā)文章就好了。

public class Main{

   public static void main(String[] args){

       // 受委托程序員大V
       Programmer programmer = new ProgrammerBigV();

       // 受委托程序員大V讓Java3y發(fā)文章,大V來(lái)點(diǎn)贊
       programmer.coding();

   }
}

此時(shí),真實(shí)對(duì)象(Java3y)對(duì)外界來(lái)說(shuō)是透明的

2.2代理類自定義方法

程序員大V看到Java3y一直順風(fēng)順?biāo)?,賺大錢了。覺(jué)得是時(shí)候要加價(jià)了,于是在點(diǎn)贊完畢后就跟Java3y說(shuō)每點(diǎn)完一次贊加100塊!

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

public class ProgrammerBigV implements Programmer{


   // ..省略了上面的代碼

   // 加價(jià)啦
   public void addMoney(){
       System.out.println("這次我要加100塊");
   }

   @Override
   public void coding(){

       // 讓Java3y發(fā)文章了
       java3y.coding();

       // 程序員大V點(diǎn)贊評(píng)論收藏轉(zhuǎn)發(fā)!
       upvote();

       // 加價(jià)
       addMoney();

   }
}

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

給女朋友講解什么是代理模式

三、動(dòng)態(tài)代理

幾年時(shí)間過(guò)去了,Java3y靠著程序員的大V點(diǎn)贊還是沒(méi)發(fā)財(cái)(本質(zhì)上Java3y還沒(méi)有干貨,沒(méi)受到大眾的認(rèn)可)。此時(shí)已經(jīng)有很多人晉升成了程序員大V了,但是之前的那個(gè)程序員大V還是一直累加著錢…雖然在開始的時(shí)候Java3y嘗到了甜頭,但現(xiàn)在Java3y財(cái)政已經(jīng)匱乏了。

Java3y將自己的失敗認(rèn)為:一定是那個(gè)程序員大V轉(zhuǎn)門為我點(diǎn)贊被識(shí)破了,吃瓜群眾都知道了,他收費(fèi)又那么貴。

于是Java3y不請(qǐng)程序員大V了,請(qǐng)水軍來(lái)點(diǎn)贊(水軍便宜,只要能點(diǎn)贊就行了):

public class Main{

   public static void main(String[] args1){

       // Java3y請(qǐng)水軍
       Java3y java3y = new Java3y();

       Programmer programmerWaterArmy = (Programmer) Proxy.newProxyInstance(java3y.getClass().getClassLoader(), java3y.getClass().getInterfaces(), (proxy, method, args) -> {

           // 如果是調(diào)用coding方法,那么水軍就要點(diǎn)贊了
           if (method.getName().equals("coding")) {
               method.invoke(java3y, args);
               System.out.println("我是水軍,我來(lái)點(diǎn)贊了!");

           } else {
               // 如果不是調(diào)用coding方法,那么調(diào)用原對(duì)象的方法
               return method.invoke(java3y, args);
           }

           return null;
       });

       // 每當(dāng)Java3y寫完文章,水軍都會(huì)點(diǎn)贊
       programmerWaterArmy.coding();

   }

}

每當(dāng)Java3y發(fā)文章的時(shí)候,水軍都會(huì)點(diǎn)贊。

給女朋友講解什么是代理模式

Java3y感嘆:請(qǐng)水軍真是方便啊~

3.1動(dòng)態(tài)代理調(diào)用過(guò)程

我們來(lái)看看究竟是怎么請(qǐng)水軍的:

Java提供了一個(gè)Proxy類,調(diào)用它的newInstance方法可以生成某個(gè)對(duì)象的代理對(duì)象,該方法需要三個(gè)參數(shù):

給女朋友講解什么是代理模式
  • 參數(shù)一:生成代理對(duì)象使用哪個(gè)類裝載器【一般我們使用的是被代理類的裝載器】

  • 參數(shù)二:生成哪個(gè)對(duì)象的代理對(duì)象,通過(guò)接口指定【指定要被代理類的接口】

  • 參數(shù)三:生成的代理對(duì)象的方法里干什么事【實(shí)現(xiàn)handler接口,我們想怎么實(shí)現(xiàn)就怎么實(shí)現(xiàn)】

在編寫動(dòng)態(tài)代理之前,要明確幾個(gè)概念:

  • 代理對(duì)象擁有目標(biāo)對(duì)象相同的方法【因?yàn)閰?shù)二指定了對(duì)象的接口,代理對(duì)象會(huì)實(shí)現(xiàn)接口的所有方法】

  • 用戶調(diào)用代理對(duì)象的什么方法,都是在調(diào)用處理器的invoke方法?!颈粩r截】

  • 使用JDK動(dòng)態(tài)代理必須要有接口【參數(shù)二需要接口】

上面也說(shuō)了:代理對(duì)象會(huì)實(shí)現(xiàn)接口的所有方法,這些實(shí)現(xiàn)的方法交由我們的handler來(lái)處理!

  • 所有通過(guò)動(dòng)態(tài)代理實(shí)現(xiàn)的方法全部通過(guò)invoke()調(diào)用

給女朋友講解什么是代理模式

所以動(dòng)態(tài)代理調(diào)用過(guò)程是這樣子的:

給女朋友講解什么是代理模式

3.2靜態(tài)代理和動(dòng)態(tài)代理的區(qū)別

很明顯的是:

  • 靜態(tài)代理需要自己寫代理類-->代理類需要實(shí)現(xiàn)與目標(biāo)對(duì)象相同的接口

  • 而動(dòng)態(tài)代理不需要自己編寫代理類--->(是動(dòng)態(tài)生成的)

使用靜態(tài)代理時(shí):

  • 如果目標(biāo)對(duì)象的接口有很多方法的話,那我們還是得一一實(shí)現(xiàn),這樣就會(huì)比較麻煩

使用動(dòng)態(tài)代理時(shí):

  • 代理對(duì)象的生成,是利用JDKAPI,動(dòng)態(tài)地在內(nèi)存中構(gòu)建代理對(duì)象(需要我們指定創(chuàng)建 代理對(duì)象/目標(biāo)對(duì)象 實(shí)現(xiàn)的接口的類型),并且會(huì)默認(rèn)實(shí)現(xiàn)接口的全部方法。

四、典型應(yīng)用

我們之前寫中文過(guò)濾器的時(shí)候,需要使用包裝設(shè)計(jì)模式來(lái)設(shè)計(jì)一個(gè)request類。如果不是Servlet提供了實(shí)現(xiàn)類給我們,我們使用包裝設(shè)計(jì)模式會(huì)比較麻煩

現(xiàn)在我們學(xué)習(xí)了動(dòng)態(tài)代理了,動(dòng)態(tài)代理就是攔截直接訪問(wèn)對(duì)象,可以給對(duì)象進(jìn)行增強(qiáng)的一項(xiàng)技能

4.1中文過(guò)濾器

    public void doFilter(final ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException{
       final HttpServletRequest request = (HttpServletRequest) req;
       HttpServletResponse response = (HttpServletResponse) resp;

       response.setContentType("text/html;charset=UTF-8");
       request.setCharacterEncoding("UTF-8");


       //放出去的是代理對(duì)象
       chain.doFilter((ServletRequest) Proxy.newProxyInstance(CharacterEncodingFilter.class.getClassLoader(), request.getClass().getInterfaces(), new InvocationHandler() {
           @Override
           public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{

               //判斷是不是getParameter方法
               if (!method.getName().equals("getParameter")) {

                   //不是就使用request調(diào)用
                  return method.invoke(request, args);
               }

               //判斷是否是get類型的
               if (!request.getMethod().equalsIgnoreCase("get")) {
                  return method.invoke(request, args);
               }

               //執(zhí)行到這里,只能是get類型的getParameter方法了。
               String value = (String) method.invoke(request, args);
               if (value == null) {
                   return null;
               }
               return new String(value.getBytes("ISO8859-1"), "UTF-8");
           }

       }), response);

   }

五、總結(jié)

第一次以這種方式寫文章,舉的例子可能會(huì)不妥,希望大家見諒~

本文主要講解了代理模式的幾個(gè)要點(diǎn),其實(shí)還有一些細(xì)節(jié)的:比如“強(qiáng)制代理”(只能通過(guò)被代理對(duì)象找到代理對(duì)象,不能繞過(guò)代理對(duì)象直接訪問(wèn)被代理對(duì)象)。只是用得比較少,我就不說(shuō)了~~

要實(shí)現(xiàn)動(dòng)態(tài)代理必須要有接口的,動(dòng)態(tài)代理是基于接口來(lái)代理的(實(shí)現(xiàn)接口的所有方法),如果沒(méi)有接口的話我們可以考慮cglib代理。

cglib代理也叫子類代理,從內(nèi)存中構(gòu)建出一個(gè)子類來(lái)擴(kuò)展目標(biāo)對(duì)象的功能

這里我就不再貼出代碼來(lái)了,因?yàn)閏glib的代理教程也很多,與動(dòng)態(tài)代理實(shí)現(xiàn)差不多~~~

總的來(lái)說(shuō):代理模式是我們寫代碼中用得很多的一種模式了,Spring的AOP底層其實(shí)就是動(dòng)態(tài)代理來(lái)實(shí)現(xiàn)的-->面向切面編程。具體可參考我之前寫的那篇文章:

  • Spring【AOP模塊】就這么簡(jiǎn)單

其實(shí)只要記住一點(diǎn):原有的對(duì)象需要額外的功能,想想動(dòng)態(tài)代理這項(xiàng)技術(shù)

參考資料:

  • 《設(shè)計(jì)模式之禪》

  • https://wangjingxin.top/2016/11/16/proxy/

  • https://www.cnblogs.com/doucheyard/p/5737366.html


新聞名稱:給女朋友講解什么是代理模式
本文路徑:http://weahome.cn/article/ipcsdc.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部