黑马程序员_代理设计模式与反射

android培训java培训

 

代理设计模式简介:

代理设计就是指由一个代理主题来操作真是主题,真是主题操作具体的业务,而代理主题负责相关业务。

       Windows系统提供快捷方式,可以是任何对象同时出现在多个地方而不必修改原始对象。对快捷方式的调用与对原始对象的调用是一样的,快捷方式对于客户端是完全透明的。快捷方式被删除了,不会影响原始对象,但原始对象被删除后,快捷方式将不能使用,这就是一种代理模式的体现。

代理模式的结构:

抽象主题:声明真实主题和代理主题的共同接口,这样任何可以使用真是主题的地方都可以使用代理主题。

代理主题:代理主题内涵有对真是主题对象的引用,从而合适是代理主题操作真是主题。代理主题提供一个与真实主题相同的接口,这样就可以在任何时候替代真是主题。

真实主题:代理主题所引用的真实主题。

静态代理:

定义代理与真实主题的共同接口:

publicinterface ISubject {

       public String print()throws Exception;

}

定义真实主题,真实主题实现抽象主题接口,并且会被代理主题所引用:

publicclass ReaSubjectImplimplements ISubject {

       @Override

       public String print()throws Exception {

              return"This is print() in RealSubject.class!!!";

       }

}

定义代理主题:

publicclass ProxySubjectImplimplements ISubject {

       private ISubjectsubject;

       public ProxySubjectImpl(ISubjectsubject) {

              this.subject =subject;

       }

       @Override

       public String print()throws Exception {

              System.out.println(this.before());// 调用代理类中的主题

              System.out.println(subject.print());// 调用真实类主题

              System.out.println(this.after());// 调用代理类中的主题

              return"Proxy is ending!!!";

       }

       public String before() {

              return"This is before() in ProxySubject.class!!!";

       }

       public String after() {

              return"This is after() in ProxySubject.class!!!";

       }

}

测试:

publicclass TestStaticProxy {

       publicstaticvoid main(String[] args)throws Exception {

              ISubject subject =null;

              //像代理主题传入真是主题的引用

              subject = new ProxySubjectImpl((ISubject)new ReaSubjectImpl());

              System.out.println(subject.print());

       }

}

Sequence图:


动态代理:

静态代理的缺点是每一个代理类只能为一个接口提供服务,很多个接口就需要有很多个代理类,最好是能有一个类可完成任意接口的代理。java.lang.reflect包中提供了三个直接支持代理模式的类:Proxy、InvocationHandler、Method。

Proxy类提供了一个创建代理对象的方法:

Public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException

newProxyInstance()可以直接创建动态代理对象,该代理对象实现了参数中interfaces指定的所有接口,执行代理对象的每个方法时都会被替换为InvocationHandler接口的invoke(),newProxyInstance()也被要求传出一个InvocationHandler的实例对象。程序每生成一个代理类对象都有一个与之关联的InvocationHandler对象。

InvocationHandler中的invoke():
Object invoke(Object proxy,Method method,Object[] args)throws Throwable
proxy:被动态代理的对象
method:正在调用的方法
args:调用被代里对象时传入的参数

Proxy类能能够在程序运行时自动创建对原始对象的代理对象,当有代理对象后,对原始对象的方法进行调用时会首先分派给InvocationHandler接口,在接口的invoke()方法中截获对原对象方法的调用,加入额外的操作,就实现了动态代理的功能。

范例1:为一个Vector类提供一个代理对象,当Vector类调用任何方法之前、之后打印两条信息,表明当调用Vector中的方法时,可以被InvocationHandler接口中的invoke()截获,并实现代理功能。

publicclass VectorProxyimplements InvocationHandler {

       private ObjectproxyObj;

       public VectorProxy(Object proxyObj) {

              this.proxyObj = proxyObj;

       }

       /**

        * 定义静态工厂方法,接收被代理的对象

        *  @param obj

        * @return

        */

       publicstatic Object factory(Object obj) {

              Class<?> cls = obj.getClass();

       /*第三个参数无法使用this,因为在静态工厂方法中,staticthis冲突 */

              return Proxy.newProxyInstance(cls.getClassLoader(),

                            cls.getInterfaces(),new VectorProxy(obj));

       }

       @Override

       public Object invoke(Object proxy, Method method, Object[] args)

                     throws Throwable {

              System.out.println("befroe overried invoke()-->" + method);

              if (args !=null) {

                     for (Object o : args)

                            System.out.println(o +"\t");

              }else {

                     System.out.println("args is null in overried invoke()");

              }

              Object obj = method.invoke(proxyObj, args);

              System.out.println("after overried invoke()-->" + method);

              return obj;

       }

 

       publicstaticvoid main(String[] args) {

              @SuppressWarnings({"unchecked", "rawtypes" })

              List<String> list = (List<String>) VectorProxy.factory(new Vector());

              list.add("New");

              System.out.println();

              list.add("York");

              System.out.println(list);

       }

}

数出结果:

befroe overried invoke()-->public abstract boolean java.util.List.add(java.lang.Object)

New    

after overried invoke()-->public abstract boolean java.util.List.add(java.lang.Object)

 

befroe overried invoke()-->public abstract boolean java.util.List.add(java.lang.Object)

York    

after overried invoke()-->public abstract boolean java.util.List.add(java.lang.Object)

 

befroe overried invoke()-->public java.lang.String java.lang.Object.toString()

args is null in overried invoke()

after overried invoke()-->public java.lang.String java.lang.Object.toString()

[New, York]

数出结果显示了在调用Vector类中add()的方法时打印了befroe、after两条信息,在直接打印集合时,因为民有参数,agrs为空的信息也打印了。代理对象截获了Vector对象的所有应用。


例2:把之前的静态代理,改成动态代理,实现代理功能

定义代理与真实类的共同接口:

publicinterface ISubject {

       public String print()throws Exception;

}

定义动态代理类,实现InvocationHandler接口,与之前的静态代理类完全不一样

publicclass DynamicProxyimplements InvocationHandler {

       private ObjecttargetObject;// 被代理的对象

       public Object createProxyInstance(Object targetObject) {

              this.targetObject = targetObject;

              //Proxy为专门完成代理的操作类

              return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),

                            targetObject.getClass().getInterfaces(),this);

              // newProxyInstance(加载接口的实现类(类的加载器),真实类实现的接口,得到InvocationHandler接口的子类(也就是本类DynamicProxy))

       }

       @Override

       public Object invoke(Object proxy, Method method, Object[] args)

                     throws Throwable {

              System.out.println(proxyer());// 调用真实类前所执行的方法

// 调用真实类中的方法

              Object obj = method.invoke(targetObject, args);

              return obj;

       }

       private String proxyer() {

              return"This is proxyer in invode()!!!";

       }

}

测试类:

publicclass DynamicProxyTest {

       publicstaticvoid main(String[] args)throws Exception {

              DynamicProxy dProxy =new DynamicProxy();

              ISubject subject = (ISubject) dProxy.createProxyInstance(new RealSubjectImpl());

              System.out.println(subject.print());

       }

}

打印结果:

This is proxyer in invode()!!!

This is RealSubject!!!

例3:采用匿名内部类的方式代理Collection接口

publicclass DynamicProxyTest{

       publicstaticvoid main(String[] args)throws Exception {

              Class<?>clazzProxy = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);

              Collection c = (Collection) Proxy.newProxyInstance(

                            Collection.class.getClassLoader(),

                            newClass[]{Collection.class},

                            new InvocationHandler(){

                                   List list = null;

                                   @SuppressWarnings("rawtypes")

                                   @Override

                                   public Object invoke(Object proxy, Method method,

                                                Object[] args) throws Throwable {

                                         if(list==null)

                                          list = new ArrayList();

                                         return method.invoke(list, args);

                                   }

                            });

              c.add("A");

              c.add("B");

              c.add("C");

              System.out.println(c.size());

              System.out.println(c);

              System.out.println(c.getClass());

       }

}

 

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值