代理模式

作者:碳水怪兽👾 发布于:2021/10/18

定义

代理模式为其他对象提供一种代理,以控制对这个对象的访问

代理模式的优点

  • 对被代理对象提供保护
  • 增强被代理对象功能

类图

案例

小张即将要从大学毕业去另一个城市工作,面临的第一个问题就是找房子,小张人生地不熟,于是找了一个中介帮忙找房,这里的中介其实就是代理

  • IRentHouse接口

    public interface IRentHouse {
    
        void rent();
    }
    
  • Graduate类

public class Graduate implements IRentHouse{

    private String name;

    public Graduate(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public void rent() {
        System.out.println("人生地不熟,找房子好难啊");
    }
}
  • RentalAgency

    public class RentalAgency implements IRentHouse{
    
        private Graduate graduate;
    
        public RentalAgency(Graduate graduate) {
            this.graduate = graduate;
        }
    
        @Override
        public void rent() {
            System.out.print(String.format("%s说:",graduate.getName()));
            graduate.rent();
            System.out.println(String.format("中介说:不要怕,我来帮%s找房子并和房东签订合同",graduate.getName()));
        }
    }
    
    
  • Client类

    public class Client {
    
        public static void main(String[] args) {
            Graduate xiaozhang = new Graduate("小张");
            RentalAgency agency = new RentalAgency(xiaozhang);
            agency.rent();
        }
    }
    

    动态代理

    上面提到的那种就是静态代理,可以发现静态代理每增加一个代理都需要创建一个新的类,增加了维护和开发的成本,为了解决这个问题,我们可以在运行时生成代理类,这种方式就称为动态代理。

    下面通过JDK动态的方式来重构上面的代码

    public class DynamicProxy implements InvocationHandler{
    
        private Graduate graduate;
    
        public DynamicProxy(Graduate graduate) {
            this.graduate = graduate;
        }
    
        @Override
        public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
            before();
            Object result = method.invoke(this.graduate,objects);
            after();
            return result;
        }
    
        public IRentHouse getProxy(Graduate graduate){
            Class<?> clazz = graduate.getClass();
            return (IRentHouse) Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
        }
    
        private void before(){
            System.out.println(graduate.getName() + "说:");
        }
    
        private void after(){
    
        }
    
    }
    
    

代理模式的应用

  • Spring#AOP
  • Mybatis