代理模式是JAVA中最常见的23中设计模式之一,既指的是客户端不直接调用实际的对象,而是通过代理调用代理,来间接调用时机的对象,为什么要采用这种间接的形式来调用对象呢?一般是因为客户端不想直接访问实际的对象,或者访问实际的对象存在困难,因此通过一个代理对象来完成间接的访问。
在现实生活中,这种情形非常的常见,比如请一个律师代理来打官司。或者是“中介”。
代理模式的实现
代理又分为:静态代理和动态代理
1.静态代理
1.创建服务类接口
public interface BuyHouce{
void buyHouce();
}
2.实现服务接口
public class BuyHouceImpl implements BuyHouce{
@Override
public void buyHouce() {
System.out.println("我要买房");
}
}
3.创建代理类
public class proxyBuyHouce implement BuyHouce{
private BuyHouce buyhouce;
public proxyBuyHouce (BuyHouce buyhouce){
this.buyhouce = buyhouce;
}
@Override
public void buyHouce() {
Random rand = new Random();
if(rand.nextBoolean()){
buyHouse.buyHosue();
}else {
System.out.println(“没钱买房!”);
} }
}
静态代理总结:
优点:可以做到在符合开闭原则的情况下对目标对象进行功能扩展。
缺点:我们得为每一个服务都得创建代理类,工作量太大,不易管理。同时接口一旦发生改变,代理类也得相应修改。
2.动态代理
动态代理有别于静态代理,是根据代理的对象,动态创建代理类。这样,就可以避免静态代理中代理类接口过多的问题。动态代理是实现方式,是通过反射来实现的。
动态代理又分为:jdk代理和CGLIB代理
使用JDK代理
1.不变 还是创建服务类接口
2.也不变也是创建服务接口
3.创建代理类就变了
public class proxyBuyHouce implements InvocationHandler {
private Object object;
public proxyBuyHouce (Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(object, args);//invoke和invokeSuper的区别?
return result;
}
4.编写测试类:
public class DynamicProxyTest {
public static void main(String[] args) {
BuyHouse buyHouse = new BuyHouceImpl ();
BuyHouse proxyBuyHouse = (BuyHouse) Proxy.newProxyInstance(BuyHouse.class.getClassLoader(),
new Class[]{BuyHouse.class}, new DynamicProxyHandler(buyHouse));
proxyBuyHouse.buyHosue();
}
}
使用CGLIB代理
1.创建接口服务 类
/**
* 目标对象,没有实现任何接口
*/
public class BuyHouce{
void buyHouce(){
System.out.println("我要买房");
};
}
2.创建代理类 不变 变得intercept 方法
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object result = methodProxy.invokeSuper(o,objects);
//这里推荐使用 invokeSuper 方法 如果使用Invoke 方法 就是JDK代理了,对于 JDK代理 invoke传入的参数object必须是代理的实例,而不是形式参数(object),否则会导致死循环,
return result;
}
3.编写测试类
public class ProxyTest{
@Test
public void test(){
//目标对象
BuyHouce target = new BuyHouce();
//代理对象
BuyHouceproxy = (BuyHouce)new ProxyFactory(target).getProxyInstance();
//执行代理对象的方法
proxy.save();
}
}
代理模式总结:
1.职责清晰:真实的角色实现实际的业务逻辑,不用关心其他非核心的业务逻辑。业务是业务,辅助功能是辅助功能,职责非常清晰。比如要实现日志功能,不用耦合在实际的业务代码中,只要做一个代理即可。
2.良好的扩展性:由于核心的业务逻辑已经封装好了,后面要增强业务功能,也可以使用代理模式代理增加功能即可。
代理模式的使用场景:
1.方法增强:比如增加日志,事务等等,
2.远程RPC调用:现在很多分布式系统调用都是采用了代理模式,
3.懒加载:有些框架会在开始的时候使用代理类来替换实际类,等到真正要使用该类的时候才进行加载,从而达到了懒加载的效果。
总结
代理模式分为静态代理和动态代理,动态代理又分为jdk动态代理和CGLIB动态代理。JDK动态代理必须要有接口才能使用,CGLIB弥补了这个缺陷,可以直接对类进行代理。同时CGLIB动态代理性能相对于JDK动态代理要优秀。
网友评论