『怎么用』代理模式

阐述

为一个对象提供一个占位符或者是替身,用以控制对这个对象的访问;
使用代理模式创建代理对象,代理对象用以访问被代理的对象。被代理对象可以远程对象、创建时开销大的对象、需要安全控制的对象。

  • 远程代理
    远程代理作为另一个JVM上对象的本地代表。调用代理上方法时,远程代理通过网络将请求传输到远程,并将结果再通过网络传输到本地,后返回给调用方。

  • 虚拟代理
    虚拟代理作为创建时开销大的对象的代表。虚拟代理经常直到我们真正需要一个对象的时候,才会去创建这个对象。在对象创建前、创建中的时候,这个对象的访问都由虚拟代理代表。在对象创建完成之后,虚拟代理才会将对象的访问委托给它所代理的对象。

    • 缓存代理(Caching Proxy)
      为开销大的运算结果提供暂时存储:它也允许多个客户共享结果,以减少计算或者网络延迟。
  • 保护代理
    根据权限不同,控制对被代理对象的访问。

    • 防火墙代理(Firewall Proxy)
      控制网络资源的访问,保护“主题”免于“坏客户”的侵害。
    • 智能引用代理 (Smart Reference Proxy)
      当主题被引用时,进行额外的动作,例如计算一个对象被引用的次数。
原理

在这里插入图片描述
在这里插入图片描述

例子

在这里插入图片描述

//subject
public interface PersonBean {
    String getName();
}
//real subject
public class PersonBeanImpl implements PersonBean {
    private String name;
    
    @Override
    public String getName() {
        return name;
    }
}
//handler
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class NotOwnerInvocationHandler implements InvocationHandler {
	//持有project
    private PersonBean personBean;

    NotOwnerInvocationHandler(PersonBean personBean) {
        this.personBean = personBean;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if ("getIdCard".equals(method.getName())){
            throw new IllegalArgumentException("又不是你的资料,你瞅啥");
        }
        return method.invoke(personBean,args);
    }
}

import java.lang.reflect.Proxy;
public class ProxyUtil {

    public static PersonBean getOwnerProxy(PersonBean personBean){
        return (PersonBean) Proxy.newProxyInstance(
                personBean.getClass().getClassLoader(),
                personBean.getClass().getInterfaces(),
                new OwnerInvocationHandler(personBean)
        );
    }

    public static PersonBean getNotOwnerProxy(PersonBean personBean){
        return (PersonBean) Proxy.newProxyInstance(
                personBean.getClass().getClassLoader(),
                personBean.getClass().getInterfaces(),
                new NotOwnerInvocationHandler(personBean)
        );
    }
}

//test
private void drive(){
     PersonBean tom = new PersonBeanImpl("tom");

     PersonBean ownerProxy = ProxyUtil.getOwnerProxy(tom);
     System.out.println("ownerProxy.getIdCard() = " + ownerProxy.getIdCard());

     PersonBean notOwnerProxy = ProxyUtil.getNotOwnerProxy(tom);
     try {
         System.out.println("notOwnerProxy = " + notOwnerProxy.getIdCard());
     } catch (Exception e) {
         e.printStackTrace();
     }
}
总结
  • 你以为你用的是Object,但其实你用的是ProxyObject。“I am watching you , I can touch you .’”
  • ProxyInvocationHandler 都在 java.lang.reflect
  • Proxy创建代理对象,InvocationHandler可以决定是否要将请求真正委托给代理对象。
Q&A
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高级摸鱼工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值