静态代理、动态代理
//接口类
public interface ICar {
void drive();
}
静态代理
目标类实现接口,代理类实现目标类的接口,通过代理类访问目标类的方法。
//目标类
public class Car implements ICar {
@Override
public void drive() {
System.out.println("开车");
}
}
//代理类
public class CarProxy implements ICar {
private ICar car;
public CarProxy(ICar car) {
this.car = car;
}
@Override
public void drive() {
System.out.println("洗车");
car.drive();
System.out.println("停车");
}
}
//测试类
public class Test {
public static void main(String[] args) {
//静态代理
System.out.println("静态代理:----->");
ICar car = new Car();
ICar proxy = new CarProxy(car);
proxy.drive();
}
}
静态代理:----->
洗车
开车
停车
优点
- 给对象增加了本地化的扩展性,增加了存取操作控制,静态代理对客户(测试类)隐藏了被代理类接口(目标类接口)的具体实现类,在一定程度上实现了解耦合,同时提高了安全性。
缺点
- 每一个需要代理的对象都要新建一个代理类,会产生多余的代理类
- 静态代理只能对某个固定接口的实现类进行代理服务,其灵活性不强。故一般大项目不会选择静态代理。
动态代理(JDK动态代理)
动态代理能够实现代理类无需和被代理类直接关联,但是动态代理类必须实现InvocationHandler
接口,并实现invoke
方法。
//目标类
public class Car implements ICar {
@Override
public void drive() {
System.out.println("开车");
}
}
//代理工具类
public class ProxyClass {
public static <T> T proxy(T tClass) {
return (T) Proxy.newProxyInstance(tClass.getClass().getClassLoader(), tClass.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("洗车");
Object invoke = method.invoke(tClass);
System.out.println("停车");
return invoke;
}
});
}
}
//测试类
public class Test {
public static void main(String[] args) {
//动态代理
ICar car = new Car();
System.out.println("动态代理:----->");
ICar iCar = ProxyClass.proxy(car);
iCar.drive();
}
}
动态代理:----->
洗车
开车
停车
优点
- 动态代理实现了只需要将被代理对象作为参数传入代理类就可以获取代理类对象,从而实现类代理,具有较强的灵活性。
- 动态代理的服务内容不需要像静态代理一样写在每个代码块中,只需要写在invoke()方法中即可,降低了代码的冗余度。
缺点
- 动态代理类仍然需要实现接口。
Retrofit就使用了JDK动态代理。