---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
final修饰的属性、方法、类分别表示为属性不可变,方法不可复写、类不可继承
代理的作用与概念
代理模式一般涉及到三个角色:
抽象角色:声明真实对象和代理对象的共同接口;
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
有一个已经开发好的类,但是现在要为其增加异常处理、日志、统计方法的运行时间、事务处理等功能,但是开发好的类不能修改或者没有办法修改,该如何做?
2、代理类和目标类
(1)、目标类
已经开发好且不能被修改的类称为目标类
(2)、代理类和目标类的关系
代理类的功能与目标类的功能一样
只是在执行目标类相关功能的前或者后增加了新的辅助功能。
代理类的每个方法名与目标类的每个方法名都一样
代理类的每个方法都要调用目标类的每个方法
代理类的每个方法在调用目标类的每个方法的前或者后都会加上系统的额外功能
客户端不直接使用目标类,而是直接使用代理类,代理类实际上是在调用目标类的功能。
3、 代理类出现前后对比
(1)、代理类出现之前,客户端直接调用目标类的功能
(2)、代理类出现之后
客户端不直接调用目标类的功能,而是直接调用与目标类相对应的代理类的功能
为了保证代理类和目标类具有相同的功能,代理类和目标类必须实现相同的接口
代码示例如下(四个类很好的诠释了代理):
package cn.itcast.ly;
//该类是抽象角色,作用是为代理类和目的类提供相同的“接口”
public abstract class AbstractRole {
public abstract void request();
}
package cn.itcast.ly;
//该类是真实角色,也就是”局长“
public class RealRole extends AbstractRole{
public void request(){
System.out.println("我为客户办事");
}
}
package cn.itcast.ly;
//该类是代理角色,也就是“局长的秘书”
public class ProxyRole extends AbstractRole {
private RealRole rr;
public void request(){
method1();
if(rr==null){
rr = new RealRole();
}
rr.request();
method2();
}
public void method1(){
}
public void method2(){
}
}
package cn.itcast.ly;
//该类是客户类,也就是客户
public class Client {
public static void main(String[] args) {
AbstractRole abs = new ProxyRole();
abs.request();
}
}
另外,如果要按照上述的方法使用代理模式,那么真实角色必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀;此外,如果事先并不知道真实角色,该如何使用代理呢?这个问题可以通过Java的动态代理类来解决。
观察代码可以发现每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理,而且,所有的代理操作除了调用的方法不一样之外,其他的操作都一样,则此时肯定是重复代码。解决这一问题最好的做法是可以通过一个代理类完成全部的代理功能,那么此时就必须使用动态代理完成。
动态代理
动态代理的步骤:
1、定义一个实现InvocationHandle接口的代理类,并实现invoke(Object obj,Method method,Object[] objs)方法
2、创建一个被代理的类以及接口
3、调用Proxy的静态方法newProxyInstance(ClassLoader cl,Class[] interfaces,InvocationHandle h)方法创建一个代理
4、通过代理调用方法
(1)、Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method, Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。 这个抽象方法在代理类中动态实现。
(2)、Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容:
Protected Proxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。
Static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。
Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。
具体代理实现:
package cn.itcast.ly;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
//该类是秘书,动态代理类
public class DynamicProxy implements InvocationHandler{
private Object sub;
public DynamicProxy(Object obj){
sub = obj;
}
//该方法时java底层自动调用的(第一个参数指代理类,第二个参数指被代理的方法,第三个参数指被代理方法的参数)
public Object invoke(Object proxy,Method method,Object[] objs) throws Exception{
System.out.println("执行前"+method);
method.invoke(sub, objs);
System.out.println("执行后"+method);
return null;
}
}
package cn.itcast.ly;
//该接口
public interface Interface {
public abstract void request();
}
package cn.itcast.ly;
//该类是真实的类
public class RealRole implements Interface {
public void request(){
System.out.println("我是局长,我真正的办事");
}
}
package cn.itcast.ly;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;;
//客户端
public class Client {
public static void main(String[] args) throws Exception {
RealRole rr = new RealRole();
DynamicProxy dp = new DynamicProxy(rr);
//返回指定接口的代理类实例
Interface inter =(Interface) Proxy.newProxyInstance(
rr.getClass().getClassLoader(),
new Class[]{Interface.class/*rr.getClass().getInterfaces()*/},
dp);
inter.request();
}
}
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
详细请查看:http://edu.csdn.net