zoukankan      html  css  js  c++  java
  • 设计模式之代理模式

    代理模式(静态代理和动态代理)

    代理模式:我觉得就是类似于Spring AOP,在不改变原有类的情况下,给某个方法的调用加一些条件。

    代理总结(一):就是利用共同实现一个接口如下例子,租房的人和中介都实现了一个接口,所以它们都有接口IRent中的rent方法,在中介Medium类中定义共同接口类型的字段private IRent rent;然后再构建一个构造器添加一个IRent类型的形参传参入口(IRent rent)

          调用方法的时候,先new出租房人的对象实例IRent target = new Gerry();,命名为target,这个target实现了IRent接口,所以它就是 IRent类型的target,它就可以作为参数传给new Medium(IRent rent) 中的rent(target)。

          IRent proxy = new Medium(target);  然后prox.rentHouse(); 这里调用的是接口中IRent中的rentHouse();但是因为多态,会调用创建实例的时候子类(接口的实现类)中自己重写的方法,这里proxy(Medium的实例).rentHouse();调用的是Medium中介类中的方法,而中介中的rentHouse方法里的语句是rent.rentHouse();这里的rent就是上面构造器中this.rent = rent(target)传参后的target,就是Gerry的对象实例,所以就又调用Gerry中的rentHouse();了,总而实现了代理效果。在中介Medium类的rentHouse();方法中rent.rentHouse();方法执行前可以添加任意认证要求,这种功能就像是springAOP中的功能一样不是么。

        总之【核心是多态我觉得】:就是必须的实现同一个接口,这样才可以有IRent target = new Gerry();这种形式,从而有IRent proxy = new Medium(target);→proxy.rentHouse(); (rent(this.rent = rent(target).renHouse(); )   →   target.rentHouse();

        说了这么多都把自己说晕了感觉...看来还是没理解透彻,

    代理总结(二):第二个(动态代理)我觉得换汤不换药,就是动态生成代理对象而已(利用传参把请求方的实现的所有接口组成的数组传进来,然后底层让"中介"实现它们,这样就又达到了使它们实现同一个借口的目的,从而又回到了静态代理的板子。)

    一、静态代理(租房子):

      gerry需要租房子,中介帮他找房子,双方都得实现一个协议-IRent接口

      中介类中找到需要租房子的人,IRent rent;通过构造函数把传进来的租房人给rent,再用rent调用方法

    1 package deep.staticc.demo;
    2 
    3 public interface IRent {
    4 
    5     public void rentHouse(String name);
    6 }
     1 package deep.staticc.demo;
     2 
     3 
     4 
     5 /**
     6  * 场景:gerry工作非常忙,没有时间找房子,需要找一个中介帮忙
     7  * @author DeepSleeping
     8  *
     9  */
    10 public class Gerry implements IRent{
    11     
    12     @Override
    13     public void rentHouse(String name){
    14         System.out.println(name + "需要租房子");
    15     }
    16 }
     1 package deep.staticc.demo;
     2 
     3 public class Medium implements IRent {
     4 
     5     //持有目标代理类的引用
     6     private IRent rent;
     7     
     8     public Medium(IRent rent){
     9         this.rent = rent;
    10     }
    11 
    12     
    13     @Override
    14     public void rentHouse(String name) {
    15         rent.rentHouse(name);
    16     }
    17 
    18 }
     1 package deep.staticc.demo;
     2 
     3 public class TestProxy {
     4     public static void main(String[] args) {
     5         //创建目标对象
     6         IRent target = new Gerry();
     7         //创建一个代理对象
     8         IRent proxy = new Medium(target);
     9         //通过代理调用方法
    10         proxy.rentHouse("gerry");
    11     }
    12 }

    静态代理总结:局限性太大,只有共同实现了某一个接口才能够代理,即都实现了IRent接口通过多态来运转。

    二、动态代理(添加信息前进行权限认证)

    1 package deep.dynamic.demo;
    2 
    3 public interface IUserDao {
    4 
    5     void add();
    6     
    7     void deletd();
    8 
    9 }
     1 package deep.dynamic.demo;
     2 
     3 /**
     4  * 实现认证操作功能:
     5  * 项目中每一个方法的调用都需要进行4个认证
     6  * 1、是否合法
     7  * 2、是否有新增权限
     8  * 3、开启事务
     9  * 4、关闭事务
    10  * @author DeepSleeping
    11  *
    12  */
    13 public class UserDaoImpl implements IUserDao {
    14     
    15     @Override
    16     public void add(){
    17         System.out.println("新增信息");
    18     }
    19 
    20     @Override
    21     public void deletd() {
    22         System.out.println("删除信息");
    23         
    24     }
    25 }
     1 package deep.dynamic.demo.proxy;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.Method;
     5 import java.lang.reflect.Proxy;
     6 
     7 /**
     8  * 动态代理类
     9  * @author DeepSleeping
    10  *
    11  */
    12 public class ProxyClass {
    13     //目标对象
    14     private Object target;
    15     
    16     public ProxyClass(Object target){
    17         this.target = target;
    18     }
    19     
    20     /**
    21      * 创建当前目标对象代理对象
    22      * @return
    23      */
    24     public Object createProxy(){
    25         /**
    26          * loader:目标对象的类加载器
    27          * interfaces:目标对象实现的所有接口组成的数组
    28          * handler:定义一个调用目标类中方法的回调类
    29          */
    30         return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
    31                 new InvocationHandler() {
    32                     
    33                     @Override
    34                     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    35                         //进行调用前的认证
    36                         System.out.println("1、是否合法");
    37                         System.out.println("2、是否有权限");    
    38                         System.out.println("3、开启事务");
    39                         Object obj = null;
    40                         
    41                         
    42                         try {
    43                             method.invoke(target, args);
    44                             
    45                         } catch (Exception e) {
    46                             System.out.println("4、关闭事务");
    47                         }    
    48                         System.out.println("--业务执行正常--");
    49                         
    50                         return obj;
    51                     }
    52                 });
    53     }
    54 }
     1 package deep.dynamic.demo;
     2 
     3 import deep.dynamic.demo.proxy.ProxyClass;
     4 
     5 public class TestDynamicProxy {
     6 
     7     public static void main(String[] args) {
     8         //创建目标对象
     9         IUserDao target = new UserDaoImpl();
    10         //创建代理类的实例
    11         ProxyClass proxy = new ProxyClass(target);
    12         //生成对应的代理对象
    13         IUserDao userDao = (IUserDao) proxy.createProxy();
    14         userDao.add();
    15         userDao.deletd();
    16     }
    17 }

     附加:为什么可以强转IUserDao userDao = (IUserDao) proxy.createProxy();

      是因为Proxy.newProxyInstance方法的第二个参数取得了目标对象的所有实现的接口的数组,代理对象就会实现这组接口,所以我们就可以将代理对象任意强转成这组接口的任意一个。

    静态代理:共同实现一个接口,通过多态调用

    动态代理:动态地实现同一个接口(通过方法传目标对象实现过的接口,然后底层自动实现它们,这样就像静态代理那样,目标和代理对象都实现了同一个接口)然后又可以利用多态强转后调用

  • 相关阅读:
    指针理解
    http和https区别
    js 日历控件
    Linux 目录详解!(转)
    互换位置输出
    晨时跌荡起伏的心情
    c++冒泡排序
    游标使用
    防止Sql注入
    ssl加密原理
  • 原文地址:https://www.cnblogs.com/deepSleeping/p/9381965.html
Copyright © 2011-2022 走看看