设计模式之代理模式

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

代理模式:我觉得就是类似于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方法的第二个参数取得了目标对象的所有实现的接口的数组,代理对象就会实现这组接口,所以我们就可以将代理对象任意强转成这组接口的任意一个。

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

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

posted @ 2018-07-28 14:42  程序员deepz  阅读(249)  评论(1编辑  收藏  举报