代理模式一类重要的设计模式,结合code理解两种代理模式的异同。
都是有一个接口,接口中有一个方法,真实角色(要被代理的对象)实现这个接口,并重写这个方法。代理类要做的事情就是代理这个真实角色,执行真实角色重写过后的方法。代理类都要把真实角色作为自己的属性,并在方法中执行真实角色的方法。
下面分开看看两种不同的代理模式。
静态代理
实现方式
- 一个接口,一个方法
public interface Rent {
void rent();
}
- 真实角色实现这个接口,重写方法
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号");
}
}
- 代理类,实现接口,将真实角色作为自己的属性,重写方法中调用真实角色的方法
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();
}
}
- 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();
}
}
动态代理
- 一个接口,一个方法
public interface Rent {
void rent();
}
- 真实角色实现这个接口,重写方法
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号");
}
}
- 代理类实现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的代理类,无论要代理的对象是什么,代理类都不用变化,省事。