代理模式
概念
为其他对象提供一种代理以控制这个对象的访问,在某些情况下一个对象不能直接访问那个对象时,代理就起到了客户端和被代理对象(委托类)中介作用。 代理类和委托类都有同样接口。
好处
可以不用动原来类的逻辑,再次增加一些功能,符合开闭原则。真正的业务还是交给被代理对象处理的,因此在其委托被代理对象处理业务前后实现一些公共逻辑服务,例如加入缓存或日志等功能,无须修改原来的类就可以使用代理进行实现。
静态代理模式
房东(Host)与中介(Proxy)共同实现了同一个接口(出租Rent), 中介给房东代理出租房子, 在出租过程中添加了中介的附属工作.
// 租房
public interface Rent {
void rent();
}
// 房东
public class Host implements Rent {
@Override
public void rent() {
System.out.println("房东要出租房子");
}
}
public class Proxy implements Rent {
private Host host;
public Proxy(Host host) {
this.host=host;
}
@Override
public void rent() {
host.rent();
release();
see();
receive();
}
public void release(){
System.out.println("发布信息");
}
public void see(){
System.out.println("看看房子");
}
public void receive(){
System.out.println("收钱");
}
}
public class Client {
public static void main(String[] args) {
Host host =new Host();
//代理
Proxy proxy = new Proxy(host);
proxy.rent();
}
}
动态代理模式
**静态代理:代理类由程序员创建的然后编译成.class文件。但是其中缺点是,具有重复代码,灵活性不好,例如在执行接口A中所有方法之前加上日志逻辑,那么使用静态代理的话,在代理类中每个方法都得加,如果我想add 开头方法加上一种逻辑,select 开头方法加上另一种逻辑,那么就很难去实现和维护了,想解决以上困惑就要使用动态代理了。
**动态代理:**是在运行的时候,通过jvm中的反射进行动态创建对象,生成字节码对象(构造方法参数 InvocationHandler h类型),传入由我们实现InvocationHandler接口的对象,通过反射创建代理对象。 然后当调用代理对象的任何方法都会调用h中的 invoke(Object proxy,Method method,Object[] args)传入当前代理对象、当前调用的方法、方法参数值。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 动态代理处理类
public class ProxyInvocationHandler implements InvocationHandler {
// 被代理的接口
private Object target;
public void setTarget(Object target) {
this.target = target;
}
// 生成代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
// 处理代理实例, 并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 动态代理的本质, 就是使用反射机制实现
log(method.getName());
Object result = method.invoke(target, args);
return result;
}
public void log(String name){
System.out.println("执行了"+name+"方法");
}
}
使用动态代理
public class Client {
public static void main(String[] args) {
//真实角色
Rent rent = new Host();
//代理角色, 不存在
ProxyInvocationHandler pih = new ProxyInvocationHandler();
// 设置要代理的对象
pih.setTarget(rent);
//动态生成代理类
Rent proxy = (Rent) pih.getProxy();
proxy.rent();
}
}
结果输出:
执行了rent方法
房东要出租房子