乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      別裝了-第一集:代理模式、動(dòng)態(tài)代理和面向方面 - 別裝了!大家一起來魯棒啦!-loobong - JavaEye技術(shù)網(wǎng)站

       ShangShujie 2008-05-04
      Java代碼 復(fù)制代碼
      1. Public class ViewAction implements Action  
      2. {  
      3.         public void doAction()  
      4.         {  
      5.                //做View的動(dòng)作  
      6.                System.out.println(“You could view the information……”);  
      7.                ……  
      8. }  
      9. }  

      代 理的意思很好理解,它借鑒了我們?nèi)粘K玫拇淼囊馑迹壕褪潜緛碓撟约河H自去做的某件事,由于某種原因不能直接做,而只能請(qǐng)人代替你做,這個(gè)被你請(qǐng)來做事 的人就是代理。比如過春節(jié)要回家,由于你要上班,沒時(shí)間去買票,就得票務(wù)中介代你購買,這就是一種代理模式。這個(gè)情景可以形象的描述如下:

      Java代碼 復(fù)制代碼
      1. class:火車站  
      2. {  
      3.         賣票:  
      4.        {……}  
      5. }  

       

      火車站是賣票的地方,我們假設(shè)只能在火車站買到票。賣票的動(dòng)作實(shí)質(zhì)是火車站類完成的。

      Java代碼 復(fù)制代碼
      1. Class:票務(wù)中介  
      2. {  
      3.         賣票:  
      4.         {  
      5.                收中介費(fèi);  
      6.               火車站.賣票;  
      7. }  
      8. }  

       

       顧客找票務(wù)中介買票的時(shí)候,調(diào)用票務(wù)中介.賣票。票務(wù)中介其實(shí)做了兩件事,一是去火車站買票,二是不能白幫你賣票,肯定要收中介費(fèi)。而你得到的好處是不用直接去火車站買票,節(jié)省了買票的時(shí)間用來上班。     以上我們簡單模擬了代理模式的情景和為什么要使用代理模式,下面我們以一個(gè)例子來具體分析一下JAVA中的代理模式。     假設(shè)有一個(gè)信息管理系統(tǒng),用些用戶有瀏覽信息的權(quán)限,有些用戶有瀏覽、添加和修改信息的權(quán)限,還有些用戶有除了上述的權(quán)限,還有刪除信息的權(quán)限,那么我們最容易想到的做法如下:
      Java代碼 復(fù)制代碼
      1. public class ViewAction  
      2. {  
      3.         //由userId計(jì)算權(quán)限  
      4.         ……  
      5.         String permission = ……;  
      6.        if(permission.equals(Constants.VIEW))  
      7.         {  
      8.                System.out.println(“You could view the information……”);  
      9.                ……  
      10. }  
      11. }  
        其他的動(dòng)作都和瀏覽信息的動(dòng)作差不多。我們來看這樣的類,很容易看出它的一些缺點(diǎn)來:第一、它把權(quán)限計(jì)算和動(dòng)作執(zhí)行都放在一個(gè)類里,兩者的功能相互混在一起,容易造成思路的混亂,而且修改維護(hù)和測(cè)試都不好;一句話來說, 它不滿足單一職責(zé)原則 。第二是客戶調(diào)用的時(shí)候 依賴具體的類,造成擴(kuò)展和運(yùn)行期內(nèi)的調(diào)用的困難,不滿足依賴顛倒原則 ( 依賴倒轉(zhuǎn)原則(DIP)盡量依賴 抽象, 定義一個(gè)接口去實(shí)現(xiàn)它, 不要依賴 具體 ) 。

          既然有這么多的問題,我們有必要對(duì)該類進(jìn)行重新設(shè)計(jì)。其實(shí)大家早已想到,這個(gè)類應(yīng)該使用代理模式。是啊,和我們買火車票的動(dòng)作一樣,動(dòng)作類不能直接執(zhí)行那個(gè)動(dòng)作,而是要先檢查權(quán)限,然后才能執(zhí)行;先檢查權(quán)限,后執(zhí)行的那各類其實(shí)就是一個(gè)代理類,修改后的代碼如下:

      Java代碼 復(fù)制代碼
      1. public interface Action  
      2. {  
      3.         public void doAction();  
      4. }  

       

      首先是設(shè)計(jì)一個(gè)接口,用來滿足依賴顛倒原則。

      Java代碼 復(fù)制代碼
      1. Public class ViewAction implements Action  
      2. {  
      3.         public void doAction()  
      4.         {  
      5.                //做View的動(dòng)作  
      6.                System.out.println(“You could view the information……”);  
      7.                ……  
      8. }  
      9. }  

       

          這個(gè)類跟火車站一樣,是動(dòng)作的真實(shí)執(zhí)行者。
      Java代碼 復(fù)制代碼
      1. Public class ProxyViewAction implements Action  
      2. {  
      3.         private Action action = new ViewAction();  
      4.         public void doAction()  
      5.         {  
      6.                //調(diào)用權(quán)限類的方法取得用戶權(quán)限  
      7.                if(Permission.getPermission(userId).equals(Constants.VIEW))  
      8.                {  
      9.                       action.doAction();  
      10. }  
      11. }  
      12. }  
        這是代理類,很容易理解。在我們的ProxyViewAction類中,除了做了客戶真正想要做的動(dòng)作:doAction()以外,還進(jìn)行了 額外 的動(dòng)作檢查用戶的權(quán)限。而作核心動(dòng)作doAction()是在一個(gè) 干干凈凈 的類:ViewAction中進(jìn)行,這個(gè)類只做 核心動(dòng)作 ,對(duì)其他的不關(guān)心,滿足了單一職責(zé)原則。      客戶端通過調(diào)用代理類來執(zhí)行動(dòng)作 ,而代理類一是將權(quán)限判斷和動(dòng)作的執(zhí)行分離開來,滿足了單一職責(zé)原則;二是實(shí)現(xiàn)了 一個(gè)接口,從而滿足了依賴顛倒原則。比第一個(gè)思路好了很多。     代理又被稱為 委派 ,說的是代理類 并不真正的執(zhí)行那個(gè)核心動(dòng)作 ,而是委派給另外一個(gè)類去執(zhí)行,如ProxyView類中,ProxyView類并沒有真正執(zhí)行doAction()方法,而是交給ViewAction類去執(zhí)行。      我們?cè)賮砜创眍怭roxyViewAction,可以看到它不僅依賴于接口Action,而且依賴于具體的實(shí)現(xiàn)ViewAction。這樣對(duì)我們的系統(tǒng) 擴(kuò)展很不利,比如我們有Add動(dòng)作、Delete動(dòng)作、Modify動(dòng)作等等,我們需要對(duì)每一個(gè)動(dòng)作都寫一個(gè)代理類,而這些代理類都做同樣的事情,先進(jìn)行 權(quán)限判斷,然后再委派。所以我們需要對(duì)這些代理再進(jìn)行一次抽象, 讓它只依賴接口Action,而不依賴于具體的實(shí)現(xiàn)

          要實(shí)現(xiàn)這樣的想法,我們需要將代理類中的具體實(shí)現(xiàn)提走,讓代理的使用者在運(yùn)行期提供具體的實(shí)現(xiàn)類,即所謂的 依賴注入 ,如下:

      Java代碼 復(fù)制代碼
      1. Public class ProxyAction implements Action  
      2. {  
      3.         private Action action;  
      4.         public ProxyAction(Action action)  
      5.         {  
      6.                this.action = action;  
      7. }  
      8.         public void doAction()  
      9.         {  
      10.                //調(diào)用權(quán)限類的方法取得用戶權(quán)限  
      11.                if(Permission.getPermission(userId).equals(action.getClass().getName()))  
      12.                {  
      13.                       action.doAction();  
      14. }  
      15. }  
      16. }  

       

      這樣,我們就將所有實(shí)現(xiàn)了Action接口的實(shí)現(xiàn)使用一個(gè)代理類來代理它們。除了ViewAction類能用,以后擴(kuò)展的AddAction、       ModifyAction、DeleteAction類等等,都可以使用一個(gè)代理類:ProxyAction。     而我們的客戶端類似如下: Action action = ProxyAction(new ViewAction); Action.doAction();     通過對(duì)代理類的 依賴注入 , 我們使得代理類初步有了一定擴(kuò)展性。但是我們還要看到,這個(gè)代理類依賴于某一個(gè)確定的接口。這仍然不能滿足我們的實(shí)際要求,如我們的系統(tǒng)的權(quán)限控制一般是 整個(gè)系統(tǒng)級(jí)的,這樣系統(tǒng)級(jí)的權(quán)限控制,我們很難在整個(gè)系統(tǒng)里抽象出一個(gè)統(tǒng)一的接口,可能會(huì)有多個(gè)接口,按照上面的代理模式,我們需要對(duì)每一個(gè)接口寫一個(gè)代 理類,同樣,這些類的功能都是一樣的。這顯然不是一個(gè)好地解決辦法。     基于上面的原因,我們需要解決一個(gè)系統(tǒng)在沒有統(tǒng)一的接口的情況下,對(duì)一些零散的對(duì)象的某一些動(dòng)作使用代理模式的問題。JAVA API為我們引入了動(dòng)態(tài)代理或動(dòng)態(tài)委派的技術(shù)。     動(dòng)態(tài)代理的核心是 InvocationHandler接口 ,要使用動(dòng)態(tài)代理就必須實(shí)現(xiàn)該接口。這個(gè)接口的委派任務(wù)是在invoke(Object proxy, Method m, Object[] args)方法里面實(shí)現(xiàn)的: //invoke是調(diào)用的意思 //在調(diào)用核心功能之前作一些動(dòng)作 …… //調(diào)用核心功能 m.invoke(obj, args); //在調(diào)用核心功能以后做一些動(dòng)作 ……     我們可以看到動(dòng)態(tài)代理其實(shí)用的是 反射機(jī)制 來調(diào)用核心功能的:m.invoke(obj, args);正是這種反射機(jī)制的使用使得我們調(diào)用核心功能更加靈活,而 不用依賴于某一個(gè)具體的接口,而是依賴于Object對(duì)象 。

          下面我們來具體看看動(dòng)態(tài)代理或動(dòng)態(tài)委派如何使用:

      Java代碼 復(fù)制代碼
      1. public class ProxyAction implements InvocationHandler {  
      2. private Object action;  
      3. //構(gòu)造方法  
      4. public ProxyAction(Object action)  
      5. {  
      6.        this.action = action;  
      7. }  
      8. public static Object getInstance(Object action)  
      9. {  
      10.         return Proxy.newProxyInstance(action.getClass().getClassLoader(),  
      11. action.getClass().getInterfaces(),new ProxyAction(action));  
      12. }  
      13.    
      14. public Object invoke(Object proxy, Method m, Object[] args)  
      15.                throws Throwable {  
      16.           
      17.         Object result;  
      18.    
      19.        try {  
      20.                       //在委派之前作動(dòng)作,如權(quán)限判斷等  
      21.            System.out.println("before method " + m.getName());  
      22.                       //進(jìn)行委派  
      23.            result = m.invoke(action, args);  
      24.    
      25.        } catch (InvocationTargetException e) {  
      26.    
      27.            throw e.getTargetException();  
      28.    
      29.        } catch (Exception e) {  
      30.    
      31.            throw new RuntimeException("unexpected invocation exception: "  
      32.    
      33.                   + e.getMessage());  
      34.    
      35.        } finally {  
      36.                       //在委派之后做動(dòng)作  
      37.            System.out.println("after method " + m.getName());  
      38.    
      39.        }  
      40.    
      41.        return result;  
      42.    
      43.    
      44. }  
      45.    
      46. }  

       

      這個(gè)代理類,首先是實(shí)現(xiàn)了InvocationHandler接口;然后在getInstance()方法里得到了代理類的實(shí)例;在invoke()方法里實(shí)現(xiàn)代理功能,也很簡單。     下面我們來看客戶端: Action action = (Action)ProxyAction.getInstance(new ViewAction()); Action.doAction();     我們可以看到代理類對(duì)接口的依賴也轉(zhuǎn)移到了客戶端上,這樣,代理類不依賴于某個(gè)接口。對(duì)于同樣的代理類ProxyAction,我們也可以有如下的客戶端調(diào)用: Engine engine = (Engine)ProxyAction.getInstance(new EngineImpl()); Engine.execute();     只要engineImpl類實(shí)現(xiàn)了Engine接口,就可以像上面那樣使用。

           現(xiàn)在我們可以看到,動(dòng)態(tài)代理的確是擁有相當(dāng)?shù)撵`活性。但我們同時(shí)也看到了,這個(gè)代理類寫起來比較麻煩,而且也差不多每次都寫這樣千篇一律的東西,只有委派 前的動(dòng)作和委派后的動(dòng)作在不同的代理里有著不同,其他的東西都需要照寫。如果這樣的代理類寫多了,也會(huì)有一些冗余代理。需要我們進(jìn)一步優(yōu)化,這里我們使用 模板方法模式來對(duì)這個(gè)代理類進(jìn)行優(yōu)化,如下:

      Java代碼 復(fù)制代碼
      1. public abstract class BaseProxy implements InvocationHandler {  
      2. private Object obj;  
      3. protected BaseProxy(Object obj)  
      4. {  
      5.        this.obj = obj;  
      6. }  
      7. public static Object getInstance(Object obj,InvocationHandler instance)  
      8. {  
      9.         return Proxy.newProxyInstance(obj.getClass().getClassLoader(),  
      10. obj.getClass().getInterfaces(),instance);  
      11. }  
      12.    
      13. public Object invoke(Object proxy, Method m, Object[] args)  
      14.                throws Throwable {  
      15.         // TODO Auto-generated method stub  
      16.         Object result;  
      17.    
      18.        try {  
      19.    
      20.            System.out.println("before method " + m.getName());  
      21.            this.doBegin();  
      22.    
      23.            result = m.invoke(obj, args);  
      24.    
      25.        } catch (InvocationTargetException e) {  
      26.    
      27.            throw e.getTargetException();  
      28.    
      29.        } catch (Exception e) {  
      30.    
      31.            throw new RuntimeException("unexpected invocation exception: "  
      32.    
      33.                   + e.getMessage());  
      34.    
      35.        } finally {  
      36.    
      37.            System.out.println("after method " + m.getName());  
      38.            this.doAfter();  
      39.    
      40.        }  
      41.    
      42.        return result;  
      43.    
      44.    
      45. }  
      46. public abstract void doBegin();  
      47. public abstract void doAfter();  
      48.    
      49. }  
       

      這樣,代理的實(shí)現(xiàn)類只需要關(guān)注實(shí)現(xiàn)委派前的動(dòng)作和委派后的動(dòng)作就行,如下

      Java代碼 復(fù)制代碼
      1. public class ProxyImpl extends BaseProxy {  
      2. protected ProxyImpl(Object o)  
      3. {  
      4.        super(o);  
      5. }  
      6. public static Object getInstance(Object foo)  
      7. {  
      8.         return getInstance(foo,new ProxyImpl(foo));  
      9. }  
      10.    
      11. //委派前的動(dòng)作  
      12. public void doBegin() {  
      13.         // TODO Auto-generated method stub  
      14.        System.out.println("begin doing....haha");  
      15.    
      16. }  
      17.    
      18. //委派后的動(dòng)作  
      19. public void doAfter() {  
      20.         // TODO Auto-generated method stub  
      21.        System.out.println("after doing.....yeah");  
      22.    
      23. }  
      24.    
      25. }  

       

      從上面的代碼,我們可以看出代理實(shí)現(xiàn)類的確是簡單多了,只關(guān)注了委派前和委派后的動(dòng)作,這是我們作為一個(gè)代理真正需要關(guān)心的。     至此,代理模式和動(dòng)態(tài)代理已經(jīng)告一段落。我們將動(dòng)態(tài)代理引申一點(diǎn)說開去,來作為這篇文章的蛇足。      這個(gè)話題就是面向方面的編程,或者說AOP。我們看上面的ProxyImpl類,它的兩個(gè)方法doBegin()和doAfter(),這是做核心動(dòng)作之 前和之后的兩個(gè)截取段。正是這兩個(gè)截取段,卻是我們AOP的基礎(chǔ)。在OOP里,doBegin(),核心動(dòng)作,doAfter()這三個(gè)動(dòng)作在多個(gè)類里始 終在一起,但他們所要完成的邏輯卻是不同的,如doBegin()可能做的是權(quán)限,在所有的類里它都做權(quán)限;而在每個(gè)類里核心動(dòng)作卻各不相同; doAfter()可能做的是日志,在所有的類里它都做日志。正是因?yàn)樵谒械念惱?,doBegin()或doAfter()都做的是同樣的邏輯,因此我 們需要將它們提取出來,單獨(dú)分析、設(shè)計(jì)和編碼,這就是我們的AOP的思想。     這樣說來,我們的動(dòng)態(tài)代理就能作為實(shí)現(xiàn)AOP的基礎(chǔ)了。好了,就說這么多,關(guān)于AOP技術(shù),我們可以去關(guān)注關(guān)于這方面的知識(shí)。

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多