设计模式之代理模式

代理模式是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动态代理要优秀。

你可能感兴趣的:(设计模式之代理模式)