代理模式:
为一个对象提供一种代理,以控制对这个对象的访问。分为静态代理和动态代理。
什么时候要用?
(1)当我们想要隐藏某个类时,可以为其提供代理类
(2)当一个类需要对不同的调用者提供不同的调用权限时,可以使用代理类来实现
(3)当我们要扩展某个类的某个功能时,可以使用代理模式,在代理类中进行简单扩展
(4)spring的aop就是使用了动态代理。
优点
(1)将代理对象与真实被调用的目标对象分离,降低了系统的耦合度
(2)保护目标对象
(3)增强目标对象
缺点
(1)会造成系统设计中类的数目增加
(2)在客户端和目标对象之间增加了代理对象,会造成请求的处理速度变慢
(3)增加系统的复杂度
原理
使用一个代理将对象包装起来,然后用该代理对象取代原始对象,任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。
分类
静态代理
特点
静态代理的代理类和目标对象类都是在编译期确定下来的,所以不利于程序的扩展。而且,每一个代理类只能为一个接口服务,这样一来程序开发中必然产生过多的代理。
代码实现
过程大致是这样的:
(1)被代理类(actor)出现。
(2)代理类(agent)出现,并与被代理类产生关系。(通过实现同一个接口产生联系)
(3)代理类执行方法。(判断是否接受代言的方法)
package com.revision.DesignMethod.proxyPattern;
interface Work{
void decide();
}
class Actor implements Work{
@Override
public void decide() {
System.out.println("我要听从代理人的意见!请和我的代理人交流!");
}
}
class Agent implements Work{
Actor a = null;
public Agent(Actor a){
this.a = a;
}
@Override
public void decide() {
System.out.println("你好,我是代理!");
a.decide();
}
}
public class StaticProxyPattern {
public static void main(String[] args) {
//先new一个被代理对象
Actor actor = new Actor();
//代理类出现,并于被代理人产生关系
Agent agent = new Agent(actor);
//代理人替被代理人执行方法
agent.decide();
}
}
动态代理
特点
动态代理是在程序运行时根据需要动态创建目标类的代理对象,客户可通过代理类来调用其它对象的方法。动态代理加入了反射,肯定会比静态代理先进一点。
代码实现
执行思路和静态代理是一样的:
(1)被代理类出现。
(2)代理类出现,并与被代理类建立关联。
(3)代理类执行方法。(main函数中调用代理类的方法,代理类处调用被代理类的方法)
package com.revision.DesignMethod.proxyPattern;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//动态代理的使用
interface Subject{
void action();
}
//被代理类
class RealSubject implements Subject{
@Override
public void action() {
System.out.println("被代理类!");
}
}
//代理类
class MyInvocationHandler implements InvocationHandler {
Object obj;
//给被代理对象进行实例化,返回一个代理类的对象
public Object blind(Object obj){
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method,Object[] args)throws Throwable {
Object returnVal = method.invoke(obj,args);
return returnVal;
}
}
public class DynamicProxyPattern {
public static void main(String[] args) {
RealSubject real = new RealSubject();
MyInvocationHandler handler = new MyInvocationHandler();
Object obj = handler.blind(real);
Subject sub = (Subject)obj;
sub.action();
}
}