代理模式

代理模式

静态代理

​ 这里就举个例子,比如你某天要去上班,但是车突然坏了,然后你又急着去上班,所以将叫人将车拖到到店里交给修理工去修车,然后你自己就正常的去上班了。

  1. 首先定义一个接口,接口里就可以定义你需要代理的方法
public interface Repair {
    void repair();
}
  1. 定义被代理类。
public class You implements Repair{
    @Override
    public void repair() {
        System.out.println("修理汽车");
    }
}
  1. 定义代理类,注意!代理类和被代理类都需要去实现Repair接口。
// 静态代理的好处:
// 1.将修理方法交给代理类处理,You类就可以做其他的事情。比如你将修车的任务交给修理工,你自己呢就可以正常上班了。
// 2.代理类可以做很多You类做不到的事情,比如before(),after(),就例如这里的例子,如果只是你自己来修车,有可能就拿个扳手在那里敲敲打打,弄对了可能车就修好了,没弄对可能还是那样。但是如果交给代理类的话,他就直接给你来个一条龙服务了。
public class Repairman implements Repair{
    private Repair repair;

    public Repairman(Repair repair) {
        this.repair = repair;
    }

    @Override
    public void repair() {
        before();
        repair.repair();
        after();
    }

    private void before(){
        System.out.println("修理工检查问题");
    }

    private void after(){
        System.out.println("修理工给你修好车之后呢,再顺便给你的车做一次保养");
    }
}
  1. 最后写个测试类试一下。
public class Test01{
    public static void main(String[] args) {
        // 静态代理
        // 这里使用了一个例子,你汽车坏了,但是你修理起来很麻烦,只想让修理工来修,这就是代理
        // 在代码里的体现就是,两个类都实现了修理的这个接口,然后将需要被代理的对象通过参数传递给代理类,然后由代理类来调用修理方法
        Repairman repairman = new Repairman(new You());
        repairman.repair();
        // 简化一下就是这样
        //new Repairman(new You()).repair();
    }
}

总结一下,代理模式的定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介,或者说这里的修理工,让他们去做一些自己做不到或者不想做的事情。

代理模式和装饰者模式的区别

​ 可能有些人觉得这代理模式不就是对类的一个拓展吗,那和装饰者模式有啥区别?其实区别还是有的。

  1. 代理模式是让别人帮自己做一些自己做不到或者不想做的事,这种事情的重要性可能不是特别高,比如你车坏了,如果花时间自己去修车上班就迟到了,而且车坏了也可以坐公交车呀,但是上班迟到了就直接扣工资了。
  2. 装饰者模式是让自己的能力增强,使得增强后的自己能够使用更多的方法,拓展在自己基础之上的功能的。就还是这个例子,本来自己不会修车,但是想自己学习一下这个技术,以后车坏了就可以自己修车了,这就是对自己的增强。

总结一下,对于修车这件事,在自己不擅长修车的情况下,代理模式的解决办法是找修理工帮忙修车,装饰者模式的解决办法是自己学习修车的这个技术,然后自己修。同一个问题,他们最终的目的是一样的,只是解决办法不同而已。所以在实际使用的时候,要考虑到应用场景和成本来使用对应的模式。

动态代理

  1. 还是一样的代码,先定义一个接口
public interface UserService {
    void add();

    void delete();

    void update();

    void select();

}
  1. 再定义被代理类
public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        System.out.println("新增了一个用户");
    }

    @Override
    public void delete() {
        System.out.println("删除了一个用户");
    }

    @Override
    public void update() {
        System.out.println("修改了一个用户");
    }


    @Override
    public void select() {
        System.out.println("选择了一个用户");
    }
}
  1. 这里就看看动态代理具体是怎么实现的
// 动态代理
// 代理模式如静态代理的好处在不改动原本的代码的情况下,增加一些格外的功能,如这里的日志功能
// 而动态代理就是在静态代理的基础上升级,可以不用一个接口的每个实现类都去加一个代理类
// 当然这里的例子其实就是一个封装好的工具类了,可以直接拿来用了
public class ProxyDemo implements InvocationHandler {
    private Object target;

    // 将需要代理的对象传递就进来,之前是用构造来设置的,这里还是建议用set方法
    public void setTarget(Object target) {
        this.target = target;
    }

    // 生成代理类
    public Object getProxy() {
        // 这里就是通过反射获取它的类加载器,接口,第三个参数类型是InvocationHandler,因为ProxyDemo实现了InvocationHandler接口
        // 所以直接用this就行
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    // 执行
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log(method.getName());// 这就是动态代理,插入日志
        Object result = method.invoke(target, args);
        return result;
    }

    private void log(String msg) {
        System.out.println("执行了" + msg + "方法");
    }

    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        ProxyDemo proxyDemo = new ProxyDemo();
        proxyDemo.setTarget(userService);
        // 只要你是实现了UserService这个接口,无论多少个实现类,它都可以通过一个代理类搞定
        // 而静态代理就不一样了,你想要有多个实现类使用代理模式,那么你就要去写多少个代理类
        UserService service = (UserService) proxyDemo.getProxy();
        // 这里调用add方法其实就是调用了动态代理里的invoke()方法,在这个方法里又通过反射调用真正的add方法
        service.add();
        // 下面的是一样的了,不做解释
        service.update();
        service.select();
        service.delete();
    }
}

到了现在,应该已经明白代理模式是干嘛的了吧,那么spring中的AOP(面向切面)就是基于动态代理实现的,看上面的代码,我们可以在不改动原本代码的情况下,在每个方法执行后都记录一次日志,这就是面向切面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

佛祖保佑永不宕机

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

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

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

打赏作者

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

抵扣说明:

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

余额充值