zoukankan      html  css  js  c++  java
  • 设计模式(六)代理模式

    ——核心作用:通过代理,控制对对象的访问,可以详细控制访问某个(某类)对象的方法,在调用这个方法前做前置处理,从而实现将统一流程代码放到代理类中处理,调用这个方法后做后置处理。

    ——AOP(Aspect Oriented Programming面向切面编程)的核心实现机制

    ——核心角色:

      抽象角色:定义代理角色和真实角色的公共对外方法。

      真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。

           关注真正的业务逻辑。

      代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附                      加自己的操作。

           将统一的流程控制放到代理角色中处理。

    ——应用场景:

      安全代理:屏蔽对真实角色的直接访问。

      远程代理:通过代理类处理进程方法调用(RMI)。

      延迟加载:先加载轻量级的代理对象,真正需要再加载真实对象。

        (比如你要开发一个大文档查看软件,大文档中有大的图片,有可能一个图片有100MB,在打开文件时不可能将所有的图片都显示出来,这样就可以使用代理模式,当需要查看图片时,用Proxy来进行大图片的打开)

    ——分类:

      静态代理(静态定义代理类)

      动态代理(动态生成代理类)

      • JDK自带的动态代理
      • Javaassist字节码操作库实现
      • CGLIB
      • ASM(底层使用指令,可维护性较差)

    静态代理:

    1. 定义一个Star接口

     1 package com.ztq.proxy.staticProxy;
     2 
     3 public interface Star {
     4     /***
     5      * 面谈
     6      */
     7     void confer();
     8     
     9     /***
    10      * 签合同
    11      */
    12     void signContract();
    13     
    14     /***
    15      * 订票
    16      */
    17     void bookTicket();
    18     
    19     /***
    20      * 唱歌
    21      */
    22     void sing();
    23     
    24     /***
    25      * 收钱
    26      */
    27     void collectMoney();
    28 }

    2. 定义一个RealStar类

     1 package com.ztq.proxy.staticProxy;
     2 
     3 public class RealStar implements Star{
     4 
     5     @Override
     6     public void confer() {
     7         System.out.println("RealStar.confer()");
     8     }
     9 
    10     @Override
    11     public void signContract() {
    12         System.out.println("RealStar.signContract()");
    13     }
    14 
    15     @Override
    16     public void bookTicket() {
    17         System.out.println("RealStar.bookTicket()");
    18     }
    19 
    20     @Override
    21     public void sing() {
    22         System.out.println("RealStar.sing()");
    23     }
    24 
    25     @Override
    26     public void collectMoney() {
    27         System.out.println("RealStar.collectMoney()");
    28     }
    29     
    30 }

    3. 定义一个ProxyStar类

     1 package com.ztq.proxy.staticProxy;
     2 
     3 public class ProxyStar implements Star{
     4 
     5     private Star star;
     6     
     7     public ProxyStar(Star star){
     8         super();
     9         this.star = star;
    10     }
    11     
    12     @Override
    13     public void confer() {
    14         System.out.println("ProxyStar.confer()");
    15     }
    16 
    17     @Override
    18     public void signContract() {
    19         System.out.println("ProxyStar.signContract()");
    20     }
    21 
    22     @Override
    23     public void bookTicket() {
    24         System.out.println("ProxyStar.bookTicket()");
    25     }
    26 
    27     @Override
    28     public void sing() {
    29         star.sing();
    30     }
    31 
    32     @Override
    33     public void collectMoney() {
    34         System.out.println("ProxyStar.collectMoney()");
    35     }
    36     
    37 }

    4. 定义一个客户端调用

     1 package com.ztq.proxy.staticProxy;
     2 
     3 public class Client {
     4     public static void main(String[] args) {
     5         Star real = new RealStar();
     6         Star proxy = new ProxyStar(real);
     7         
     8         proxy.confer();
     9         proxy.signContract();
    10         proxy.bookTicket();
    11         proxy.sing();
    12         proxy.collectMoney();
    13     }
    14 }

    运行结果:

    ProxyStar.confer()
    ProxyStar.signContract()
    ProxyStar.bookTicket()
    RealStar.sing()
    ProxyStar.collectMoney()

    UML图:


    动态代理相比于静态代理的优点:抽象角色中(接口)声明的所有方法都被转移到调用处理器一个集中的方法中处理,这样我们可以更加灵活和统一的处理众多的方法。

    JDK自带的动态代理:

      java.lang.reflect.Proxy 作用:动态生成代理类和对象

      java.lang.reflect.InvocationHandler(处理器接口)

        可以通过invoke方法实现对真实角色的代理访问。

        每次通过Proxy生成代理类对象时都要指定对应的处理器对象。

    Star接口、RealStar类与静态代理一样,此处省略。

    定义一个StarHandler类

     1 package com.ztq.proxy.dynamicProxy;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.Method;
     5 
     6 public class StarHandler implements InvocationHandler{
     7 
     8     Star realStar;
     9     
    10     public StarHandler(Star realStar) {
    11         super();
    12         this.realStar = realStar;
    13     }
    14 
    15     @Override
    16     public Object invoke(Object proxy, Method method, Object[] args)
    17             throws Throwable {
    18         Object object = null;
    19         System.out.println("真正的方法执行前");
    20         System.out.println("面谈,签合同,预付款,订机票");
    21         if(method.getName().equals("sing")){
    22             object = method.invoke(realStar, args);
    23         }
    24         System.out.println("真正的方法执行后");
    25         System.out.println("收尾款");
    26         return object;
    27     }
    28 
    29 }

    定义一个客户端调用类

     1 package com.ztq.proxy.dynamicProxy;
     2 
     3 import java.lang.reflect.Proxy;
     4 
     5 public class Client {
     6     public static void main(String[] args) {
     7         Star realStar = new RealStar();
     8         StarHandler handler = new StarHandler(realStar);
     9         Star proxy = (Star)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Star.class}, handler);
    10         
    11         proxy.bookTicket();
    12         proxy.sing();
    13     }
    14 }

    运行结果

    真正的方法执行前
    面谈,签合同,预付款,订机票
    真正的方法执行后
    收尾款
    真正的方法执行前
    面谈,签合同,预付款,订机票
    RealStar.sing()
    真正的方法执行后
    收尾款
  • 相关阅读:
    蜘蛛修网
    推荐10款用户界面设计
    18个web开发人员必备的Chrome扩展
    分享一个帮助你在线测试响应式设计的web工具 Screenqueri.es
    推荐16款每周设计灵感
    分享一个帮助你快速构建HTML5游戏的javascript类库 CreateJS
    5个jQuery的备选轻量级移动客户端开发(Mobile development)类库
    帮助你高效开发Ajax应用的超酷jQuery插件 AjaxML
    免费资源:350个超棒标志性字符图标
    免费素材下载:超酷的简单按钮UI
  • 原文地址:https://www.cnblogs.com/zhangtianq/p/6067443.html
Copyright © 2011-2022 走看看