了解代理模式

代理模式就是当客户想访问一个对象的时候,找一个中介(代理对象)来代替真实对象。用户通过中介来实现真实对象的方法,并且在方法执行前后可以加上自己需要的其他附加操作。

1.1 静态代理

首先定义一个接口,这个接口表示一个动作,代理对象和真实对象都实现这个接口的动作。比如真实对象(房东)和代理对象(房屋中介)都实现出租房子Rent()这个接口。

接口

public interface Rent {
      //出租房屋
      public void rent();
}

真实对象(接口的实现类)

public class Host implements Rent{
      @Override
      public void rent() {
            System.out.println("房东要出租房子");
      }
}

代理对象(接口的实现类的代理类)

public class Proxy implements Rent{
      private Host host;
     =public Proxy(Host host) {
            this.host = host;
      }
      @Override
      public void rent() {
            host.rent();//调用了真实对象的方法
            seeHouse();//附加方法
            agencyFee();//附加方法
      }
      //带人看房
      public void seeHouse() {
            System.out.println("中介带人看房");
      }
      //收中介费
      public void agencyFee(){
            System.out.println("收中介费");
      }
}

想租房的人(Client)

public class Client {
      public static void main(String[] args) {
            Host host= new Host();
            //创建代理对象,传入真实对象
            Proxy proxy=new Proxy(host);
            proxy.rent();
      }
}

运行结果
在这里插入图片描述
这里没有通过真实对象(房东)来执行租房这一行为,而是由中介代理执行,这就是代理模式

代理模式最主要的就是有一个公共接口(Rent),一个具体的类(Host),一个代理类(Proxy),代理类持有具体类的实例,代为执行具体类实例方法

1.2 静态代理的缺点

  • 静态代理类需要实现目标类(被代理类)的接口,并实现其方法,造成了代码的大量冗余。比如说,想要在每个代理的方法前都加上一个处理方法,这样就需要在每一个代理类的每个代理方法前加入beforeMethod()方法

  • 静态代理只能对某个固定接口的实现类进行代理服务,一个接口的实现类对应一个代理类,其灵活性不强。故一般大项目不会选择静态代理。而动态代理一个代理类对应一个接口的所有实现类

2.动态代理

在静态代理里,代理类持有具体类的实例,代为执行具体类实例方法。
动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类中的方法。 动态代理是代理一个接口下的多个实现类

动态代理的步骤

  1. 创建InvocationHandler对象(传入真实对象),这个对象里invoke方法实现真实对象的方法和一些附加的方法
InvocationHandler handler = new MyInvocationHandler(host);
public class MyInvocationHandler implements InvocationHandler {
      //被代理的对象
      private Rent rent;

      public MyInvocationHandler(Rent rent) {
            this.rent =rent;
      }

      //处理代理实例,并返回结果
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //在这里可以加一些其他公共操作

            //args为调用方法对应的参数
            Object result=method.invoke(rent,args);

            //在这里可以加一些其他公共操作
            return result;
      }
}
  1. 创建一个新的Class对象(代理类的Class对象,用它生成代理对象proxy),拷贝接口的所有信息,这个对象中含有真实对象实现的接口中的所有方法和类结构信息,并且含有构造器(接口没有构造器,不能产生实例)
Class<?> ProxyClass = Proxy.getProxyClass(Rent.class.getClassLoader(), new Class<?>[] {Rent.class});

所以,一旦我们明确接口,完全可以通过接口的Class对象,创建一个代理Class(这个类和接口结构一样,只是多了一个构造器),通过代理Class即可创建代理对象

  1. 获得新的Class对象的带InvocationHandler参数Constructor构造器
Constructor<?> constructor = ProxyClass.getConstructor(InvocationHandler.class);
  1. 通过构造器,构造代理对象proxy
Rent proxy = (Rent) cons.newInstance(handler);
  1. 通过代理对象.方法来调用handler.invoke()方法。代理对象持有一个InvocationHandler对象,InvocationHandler对象持有一个被代理的对象,
    再联系到InvacationHandler中的invoke方法
    我们可以对InvocationHandler看做一个中介类,中介类持有一个被代理对象,在invoke方法中调用了真实对象的相应方法。通过聚合方式持有被代理对象的引用,把外部对invoke的调用最终都转为对被代理对象的调用。
proxy.rent();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值