静态代理和动态代理


代理模式一类重要的设计模式,结合code理解两种代理模式的异同。

都是有一个接口,接口中有一个方法,真实角色(要被代理的对象)实现这个接口,并重写这个方法。代理类要做的事情就是代理这个真实角色,执行真实角色重写过后的方法。代理类都要把真实角色作为自己的属性,并在方法中执行真实角色的方法。

下面分开看看两种不同的代理模式。

静态代理

实现方式

  1. 一个接口,一个方法
public interface Rent {
    void rent();
}
  1. 真实角色实现这个接口,重写方法
public class RentImpl implements Rent {
    @Override
    public void rent() {
        System.out.println("真实角色1号");
    }
}
public class RentImpl2 implements Rent {
    @Override
    public void rent() {
        System.out.println("真实角色2号");
    }
}
  1. 代理类,实现接口,将真实角色作为自己的属性,重写方法中调用真实角色的方法
public class Proxy implements Rent {
    private RentImpl rentImpl;
    public Proxy(RentImpl rentImpl){
        this.rentImpl=rentImpl;
    }
    @Override
    public void rent() {
        System.out.println("代理类执行被代理类的方法:");
        rentImpl.rent();
    }
}
public class Proxy2 implements Rent {
    private RentImpl2 rentImpl2;
    public void setRentImpl2(RentImpl2 rentImpl2) {
        this.rentImpl2 = rentImpl2;
    }
    @Override
    public void rent() {
        rentImpl2.rent();
    }
}
  1. client中新建真实角色,新建代理类,将真实角色作为代理类的属性,用代理类执行方法,实际上执行的是被代理类的方法
public class Client {
    public static void main(String[] args) {
        //构造器注入代理类的属性(真实角色)
        RentImpl imp1=new RentImpl();
        Proxy proxy = new Proxy(imp1);
        proxy.rent();
        //set注入代理类的属性(真实角色)
        RentImpl2 impl2 = new RentImpl2();
        Proxy2 proxy2 = new Proxy2();
        proxy2.setRentImpl2(impl2);
        proxy2.rent();
    }
}

动态代理

  1. 一个接口,一个方法
public interface Rent {
    void rent();
}
  1. 真实角色实现这个接口,重写方法
public class RentImpl implements Rent {
    @Override
    public void rent() {
        System.out.println("真实角色1号");
    }
}
public class RentImpl2 implements Rent {
    @Override
    public void rent() {
        System.out.println("真实角色2号");
    }
}
  1. 代理类实现invocationHandler,设置一个target属性(要代理的对象)并重新invoke方法(反射执行被代理类的方法),添加getProxyInstance方法,用于获取代理类
public class MyProxy implements InvocationHandler{
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    public Object getProxyInstance(){
        return Proxy.newProxyInstance(target.getClass().getClassLoader()
        ,target.getClass().getInterfaces(),this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(target, args);
        return result;
    }
}

4、client中新建一个真实角色,将真实角色通过set方法,作为代理类的target,同时getProxyInstance获得代理类的实例。通过代理类的实例执行方法

public class Client {
    public static void main(String[] args) {
        //真实角色
        RentImpl rent = new RentImpl();
        RentImpl2 rent2 = new RentImpl2();
        //代理类代理真实角色
        MyProxy myProxy = new MyProxy();
        //myProxy.setTarget(rent);
        myProxy.setTarget(rent2);
        //获取代理类
        Rent proxyInstance = (Rent)myProxy.getProxyInstance();
        //代理类执行方法
        proxyInstance.rent();
    }
}

两者不同之处

  • 静态代理每次有一个接口的实现类(真实角色),都要相应的新建一个代理类,将这个真实角色作为新建代理类的属性,意思就是代理类和真实角色一对一绑定的。有多少实现接口的真实角色,就有多少对应的代理类,真实角色一多,非常麻烦。
  • 动态代理只需要一个实现了InvocationHandler的代理类,无论要代理的对象是什么,代理类都不用变化,省事。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值