个人笔记之代理模式

个人笔记之静态代理和动态代理

代理模式

代理模式就是给某个目标类提供另一个特殊的类来代替这个目标类进行某些操作,并可以在实现目标类原有的功能的基础上还能提供一些其他的方法或操作。

就像代打一样,有些人技术不太好又想上分,只能去请代练代打帮忙上分,此时代打就充当了代理类的角色,原本某人能实现的功能只能打打辅助混子,而代打什么位置都能玩,拿瑶都能带飞,就相当于功能增强了,但是好友(用户)看不到具体操作。

能,插⼊的功能对于调⽤者是透明的,起到伪装控制的作⽤。如租房的例⼦:房客、中介、房东。对应

于代理模式中即:客户类、代理类 、委托类(被代理类)。

为某⼀个对象(委托类)提供⼀个代理(代理类),⽤来控制对这个对象的访问。委托类和代理类有

⼀个共同的⽗类或⽗接⼝。代理类会对请求做预处理、过滤,将请求分配给指定对象。

在JAVA的开发过程中,我们经常需要对很多

1.静态代理

静态代理时,代理的角色是固定的,也就是说一个代理类只能实现一种操作。

简单地解释,一个代打只会打一种游戏,换个游戏就要找别的人了。

上代码:

最开始,某菜鸡接触到了某者农药这款辣鸡游戏,S2奋斗至今没有上过王者,但谁让他喜欢打游戏呢

创建一个打游戏接口,目前只有农药:

package com.cl;
//定义接口,打游戏
public interface PlayGame{
    //定义方法,打某者农药
    public void playWangZheRongYao();
}

然后需要刚刚连跪十把的某永恒钻石手残菜鸡:

package com.cl;
//某手残钻石渣渣
public class MrCai implements PlayGame{
    @Override
    public void playWangZheRongYao() {
        System.out.println("某菜鸡的账号已经连跪十把了...");
    }
}

然后有一个代练大佬,王者10000星 真の强者:

package com.cl;
//代练,王者一万星
public class DaiLian implements  PlayGame{
    private PlayGame play;
    public DaiLian(PlayGame play) {
        this.play = play;
    }
    @Override
    public void playWangZheRongYao() {
        //王者大佬开始接单
        System.out.println("代练大佬接到订单...");
        //王者大佬上号就是干
        play.playWangZheRongYao();
        //经过大佬一番厮杀
        System.out.println("大佬打了一个月,打到王者一百星了...");
    }
}

那是一个风和日丽的下午,某菜找到了代练大佬,经过一番 PY 终于说动大佬出手:

package com.cl;
public class JiaoYi {
    public static void main(String[] args) {
        //菜先生连跪十把心态崩了
        MrCai cai = new MrCai();
        //找到了万星代练大佬,把菜先生的账号给大佬了
        DaiLian proxy = new DaiLian(cai);
        //大佬拿起手机就是干
        proxy.playWangZheRongYao();
    }
}

运行结果:
在这里插入图片描述
总结:通过在代理对象中调用目标对象中的方法,在增加其他操作,最后实现效果强于目标对象中的方法。这种模式的好处就是无论目标对象有什么功能,代理对象都能在实现原本功能的基础上再加上其它功能。
也就是说一个代练大佬圆了千千万万菜鸡们的王者梦想。

2.动态代理

1.动态代理的定义

在静态代理中,代理对象继承和目标对象相同的接口,然后在方法中调用目标对象的方法达到增强目标方法的目的。但是这样做的坏处就是代理对象必须继承和目标对象相同的接口才行,若有其他功能对象也想使用代理就必须重新写一个代理类,造成非常严重的代码重复和冗余,甚至会导致类爆炸的发生。

所以我们把代理对象拿出来,让它根据目标对象的类信息来选择继承哪些接口,以及接口中的方法,这样只需要写一个代理类就可以实现实现了不同接口方法的类。

静态方法的代理对象就像专属客服,动态方法的代理对象就像电话客服。

2.动态代理的实现方式

第一种:JDK动态代理

第二种:Cglib动态代理

2.1 JDK动态代理

被代理的对象必须是某接口的实现,通过方法的实现创建出相应的代理类,同样实现被代理的对象实现的接口,从而达到增强代理对象功能的方法,而由于代理类是根据被代理的对象动态生成的,所以可以对多种不同的目标对象实现方法增强。

为了体现差别,首先需要两个接口:

package com.cl.jdkdynamicproxy;

public interface PlayGame1 {
    //鲲先生喜欢吃鸡,不打王者荣耀
    public void playChiJi();
}
package com.cl.jdkdynamicproxy;

public interface PlayGame2 {
    //菜先生有空时最喜欢的事是打王者
    public void playWangZhe();
}

然后分别是两个实现类,但类的方法略显单调,需要增强:

菜先生和他的好友鲲先生,菜先生只玩王者,鲲先生只玩吃鸡

package com.cl.jdkdynamicproxy;
public class MrKun implements PlayGame1 {
    //阿菜的好友阿鲲带阿菜上分,结果也掉到了钻石
    @Override
    public void playChiJi() {
        System.out.println("阿坤连续落地成盒二十把,气的手机都砸了...");
    }
}
package com.cl.jdkdynamicproxy;
public class MrCai implements PlayGame2 {
    @Override
    public void playWangZhe() {
        System.out.println("某菜鸡王者又自己掉到钻石,心态崩了...");
    }
}

某代练大佬用挣来的钱开了个代练平台,能找到精通各种游戏的大佬:

package com.cl.jdkdynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//大佬拿挣到的钱搭了一个代练平台,请了各种游戏的代练,当然目前只有他自己
public class DaiLianPingTai implements InvocationHandler {
    //拿到一个目标对象,因为不确定对象是人是狗所以用Object类型(菜鸡玩家对象)
    private Object target;
    //给个构造器,用来传参(传入目标对象),用来让玩家进入代练平台
    public DaiLianPingTai(Object target) {
        this.target = target;
    }

    //重写的invoke方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //附加操作1
        System.out.println("代练大佬接单上号");
        //得到一个结果对象,通过使用invoke方法来调用目标中的方法,target是目标对象,args是参数
        Object result = method.invoke(target, args);
        //附加操作2
        System.out.println("代练大佬打了三个通宵还是没能上分,哭的很惨,退款了...");
        return result;
    }
    //方法,获取代理对象(找代练)
    public Object getProxy(){
        //返回一个代理类,通过当前类的类加载器,根据目标类的接口列表来动态创建了一个代理类
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
}

最后又是不可言说的交易:

package com.cl.jdkdynamicproxy;
public class JiaoYi {
    public static void main(String[] args) {
        //首先获取一个菜鸡
        MrCai mrCai = new MrCai();
        //菜鸡登录平台找到了代练大佬
        DaiLianPingTai tai = new DaiLianPingTai(mrCai);
        //大佬王者10万星,不上王者包退
        PlayGame2 proxy = (PlayGame2) tai.getProxy();
        //代练大佬上号上分
        proxy.playWangZhe();

        System.out.println("=====菜先生被大佬永久拉黑的第二天...=====");
        //坤先生也想找一个代练,于是找到这个平台
        MrKun mrKun = new MrKun();
        //注意,平台相同
        tai = new DaiLianPingTai(mrKun);
        //在平台上找了一位只玩吃鸡的大佬,不上分赔双倍
        PlayGame1 proxy1 = (PlayGame1) tai.getProxy();
        proxy1.playChiJi();

    }
}

最后是运行截图:
在这里插入图片描述
其实重点就是根据目标对象实现的接口,让一个代理类继承相同的接口从而实现方法
所以菜先生有一位即爱玩王者又爱玩吃鸡的不差钱的虚先生也想找个代练,因为某神要公测没时间玩了。实现两个接口方法就行了,时间不够就不写了。

2.2 Cglib动态代理

通过继承目标类来实现增强功能。

首先需要添加依赖:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值