代理模式:
某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。
目的:
1、通过引入代理对象的方式来间接访问目标对象,防止直接访问目标对象给系统带来的不必要复杂性;
2、通过代理对象对访问进行控制;
抽象角色:指代理角色和真实角色对外提供的公共方法,一般为一个接口。
真实角色:需要实现抽象角色接口,定义了真实角色所要实现的业务逻辑,以便供代理角色调用。也就是真正的业务逻辑在此。
代理角色:需要实现抽象角色接口,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。将统一的流程控制都放到代理角色中处理。
静态代理:
静态代理在使用时,需要定义接口或者父类,被代理对象与代理对象一起实现 相同的接口或者是 继承相同 父类。一般来说,被代理对象和代理对象是一对一的关系,当然一个代理对象对应多个被代理对象也是可以的。
静态代理,一对一则会出现时静态代理对象量多、代码量大,从而导致代码复杂,可维护性差的问题,一对多则代理对象会出现扩展能力差的问题。
动态代理:
动态代理是指客户通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。即不直接找到被代理对象,而是找被代理对象的经纪人,从而由经纪人在找到被代理对象。代理对象较多的情况下,更适合使用动态代理,降低代码量和耦合度。
动态代理实现如下:
//抽象角色
interface Api {
void test(String a);
}
//真实角色
static class ApiImpl implements Api {
@Override
public void test(String a) {
System.out.println("api 实现内容:" + a);
}
}
public static void main(final String[] args) throws Exception {
//真实角色实例
final Api api = new ApiImpl();
api.test("直接测试");
/**
* Proxy.newProxyInstance 创建了一个Class,仅在内存中生成
* Object o 为代理对象,即Proxy.newProxyInstance 的返回值
* Method method 为调用的方法
* Object[] objects 为方法传入的参数
* InvocationHandler 是监听回调,在代理对象上执行方法,都会由这个监听回调出来
*/
Object obj = Proxy.newProxyInstance(Api.class.getClassLoader(),
new Class[]{Api.class}, //JDK实现只能 代理接口
new InvocationHandler() {
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
for (Object obj : objects) {
System.out.println("传参 " + obj);
}
//执行真实对象方法
return method.invoke(api, objects);
}
}
);
//真实角色实例
Api api1 = (Api) obj;
api1.test("动态代理");
}
得到结果
api 实现内容:直接测试
动态代理测试
api 实现内容:动态代理
静态/动态 代理区别如下: