设计模式之代理模式

代理模式

1:代理模式简介

可以把代理简单的理解为中介,为目标对象提供代理对象,由代理对象去控制目标对象的引用。因此可以通过代理对象来扩展目标对象功能而无需更改目标对象

2:代理模式的主要角色

  • ISubject:抽象主题角色,目标对象和代理对象共同实现的接口。
  • TargetSubject:目标主题角色,是实现抽象主题接口的类。
  • Proxy:代理角色,也是实现抽象主题接口的类,内部含有对目标对象TargetSubject的引用,从而可以操作目标对象或者代理目标对象。同时代理对象也可以在操作目标对象的同时扩展功能。

2:代理模式主要有静态代理和动态代理

2.1静态代理

主要分组合静态代理继承静态代理

  • 组合静态代理 (代理对象存放目标对象引用)
//抽象主题
public interface Subject {
    void findLove();
}
//目标对象
public class Son implements Subject {
    @Override
    public void findLove() {
        System.out.println("我没空找女人,让我妈妈代理了");
    }
}
//代理对象
public class Mother implements Subject{
    private Son son;
    public Mother(Son son){
        this.son = son;
    }
    @Override
    public void findLove() {
        this.son.findLove();
        System.out.println("妈妈代理了你的请求帮你找女人");
        System.out.println("我要找胸大肤白貌美的");
    }
}
  • 组合静态代理 (代理对象继承目标对象)
2.2动态代理
  • jdk动态代理
//抽象主题角色
public interface Person  {
    public  void findlove();
    //扩展新的需求 要会玩
    public void play();
}
//目标主题角色
public class Gxx  implements  Person{
    @Override
    public void findlove() {
        System.out.println("要善良的女生");
    }
    @Override
    public void play() {
        System.out.println("找会玩的女生");
    }
}
//jdk代理对象
public class JDKMeipo implements InvocationHandler{
    //保存被代理对象
    private Person tartget;

    //获取被代理对象实例
    public Object getInstance(Person tartget){
        this.tartget=tartget;
        Class<?> clazz=tartget.getClass();

        //用来生成一个对象,通过字节码重组
        return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
    }

    //假如我换成其他功能,动态代理在这边还要改代码
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("我是媒婆,我要帮你找对象");
        System.out.println("开始物色");
        method.invoke(this.tartget,args);
        System.out.println("我媒婆找到了");
        return null;
    }
}
//测试类
public class JDKProxyTest {
    public static void main(String[] args) {
        Person obj=(Person) new JDKMeipo().getInstance(new Gxx());
        obj.play();
        //原理-------有兴趣的可以自行研究jdk源码
        /*
        * 1:拿到被代理对象的引用,并且获取它所有的接口(反射获取)
        * 2:通过jdk proxy 类重新生成新的类,同时新的类要实现被代理所有实现的接口
        * 3:(动态生成java代码)把新加的业务逻辑方法由一定逻辑调用
        * 4:编译新生成的java代码
        * 5:再重新加载到jvm中运行
        * 以上过程叫做字节码重组
        * jdk规范,只要是$开头的一般都是动态生成的,比如代理类,内部类
        * */
    }
}
  • cglib动态代理
//目标对象
public class ZhangS {
    public  void findLove(){
        System.out.println("张三要找白富美");
    }
}
//代理对象
public class CglibMeiPo implements MethodInterceptor {
    public  Object getInstance(Class<?> clazz){
        Enhancer enhancer=new Enhancer();

        //要把哪个类设置为即将生成的新的父类
        enhancer.setSuperclass(clazz);
        //由谁来当子类呢,自己来当子类(代理类)
        enhancer.setCallback(this);

        return enhancer.create();
    }
    //业务的增强
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("我是媒婆,我要帮你找对象");
        System.out.println("开始物色");
        methodProxy.invokeSuper(o,objects);
        System.out.println("我媒婆找到了");
        return null;
    }
}
//测试类
public class CglibTest {
    public static void main(String[] args) {
        try {
            ZhangS obj =(ZhangS) new CglibMeiPo().getInstance(ZhangS.class);
            obj.findLove();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

3:jdk动态代理和cglib动态代理对比

  • jdk的动态代理是基于类实现了接口,cglib是基于类,没有强制要求目标类一定要是实现接口。
  • jdk的核心是实现InvocationHandler接口,使用invoke()方法进行面向切面的处理,调用相应的通知。
  • cglib的核心是实现MethodInterceptor接口,使用intercept()方法进行面向切面的处理,调用相应的通知。
  • 其中cglib中有一个Enhancer类,可以使用他快速的创建一个代理类。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

mindcarver

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

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

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

打赏作者

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

抵扣说明:

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

余额充值