Java--代理模式、动态代理

代理模式是很常见的一种设计模式,如AppCompatActivity兼容方案,Java中代理模式分为静态代理和动态代理,动态代理是JVM帮助我们实现的
一、代理模式
1.代理模式场景

有一名员工A,他出于某些原因需要公司签字,老板和秘书都可以执行公司签字的职能,但是秘书没有直接签字的权力,真正签字的必须是老板,而员工并不能直接找老板签字,只能和秘书打交道。由此看出,秘书只是一个代理者,他和老板拥有相同的职能,但是最终执行职能的还是老板,是员工和老板中间的窗口

2.将上面的场景转化为代码

职能接口:

package delegate;

public interface Function {
    void sign();
}

老板:

package delegate;

class Boss implements Function {
    @Override
    public void sign() {
        System.out.println("老板开始签字");
    }
}

秘书:

package delegate;

public class Secretary implements Function {
    private final Boss boss;

    public Secretary() {
        this.boss = new Boss();
    }

    @Override
    public void sign() {
        System.out.println("秘书交由老板签名");
        boss.sign();
    }
}

员工:

package delegate.other;


import delegate.Secretary;

public class Employee {
    public static void main(String[] args) {
        Secretary secretary = new Secretary();

        System.out.println("请求签名");
        secretary.sign();
    }
}

结果:
请求签名
秘书交由老板签名
老板开始签字

3.代理模式条件

根据上面的代码,我们可以发现,代理模式有两个条件:

  • 代理类和被代理类必须有同一个父类或接口
  • 代理对象持有被代理对象
二、虚代理

kotlin中我们常常使用懒加载,只有在对象用到时,才实例化创建它,虚代理就是这种模式

1.场景

老板很忙,不一定一直都在公司,现在秘书也可以签名了,但是老板在的时候,还是优先老板签名。公司职能新增了开会,开会必须要等待老板在场

2.代码

职能接口:

package delegate;

public interface Function {
    void sign();
    void meeting();
}

老板:

package delegate;

class Boss implements Function {
    @Override
    public void sign() {
        System.out.println("老板开始签字");
    }

    @Override
    public void meeting() {
        System.out.println("老板开始开会");
    }
}

秘书:

package delegate;

public class Secretary implements Function {
    private volatile Boss boss;

    @Override
    public void sign() {
        if (boss != null) {
            System.out.println("秘书交由老板签名");
            boss.sign();
        } else {
            System.out.println("秘书开始签名");
        }
    }

    @Override
    public void meeting() {
        waitBoss();
        boss.meeting();
    }

    public void waitBoss() {
        if (boss == null) {
            synchronized (this) {
                if (boss == null) {
                    System.out.println("等待老板回公司");
                    boss = new Boss();
                }
            }
        }
    }
}

员工:

package delegate.other;


import delegate.Secretary;

public class Employee {
    public static void main(String[] args) {
        Secretary secretary = new Secretary();

        System.out.println("请求签名");
        secretary.sign();

        System.out.println("\n请求开会");
        secretary.meeting();

        System.out.println("\n请求签名");
        secretary.sign();
    }
}

结果:
请求签名
秘书开始签名

请求开会
等待老板回公司
老板开始开会

请求签名
秘书交由老板签名
老板开始签字

三、保护代理

保护代理在对象访问时进行权限检查

1.场景

老板的老婆可以问公司的效益,但员工不能问

2.代码

职能接口:

package delegate;

public interface Function {
    void sign();
    void meeting();
    void report(String who);
}

老板:

package delegate;

class Boss implements Function {
    @Override
    public void sign() {
        System.out.println("老板开始签字");
    }

    @Override
    public void meeting() {
        System.out.println("老板开始开会");
    }

    @Override
    public void report(String who) {
        System.out.println("老板开始给" + who + "打报告");
    }
}

秘书:

package delegate;

public class Secretary implements Function {
    private volatile Boss boss;

    @Override
    public void sign() {
        if (boss != null) {
            System.out.println("秘书交由老板签名");
            boss.sign();
        } else {
            System.out.println("秘书开始签名");
        }
    }

    @Override
    public void meeting() {
        waitBoss();
        boss.meeting();
    }

    @Override
    public void report(String who) {
        if (who == null) return;

        if (who.equals("老婆")) {
            waitBoss();
            boss.report(who);
        } else {
            System.out.println(who + "被开除了");
        }
    }

    public void waitBoss() {
        if (boss == null) {
            synchronized (this) {
                if (boss == null) {
                    System.out.println("等待老板回公司");
                    boss = new Boss();
                }
            }
        }
    }
}

员工:

package delegate.other;


import delegate.Secretary;

public class Employee {
    public static void main(String[] args) {
        Secretary secretary = new Secretary();

        System.out.println("老婆请求报告");
        secretary.report("老婆");

        System.out.println("\n张三请求报告");
        secretary.report("张三");
    }
}

结果:
老婆请求报告
等待老板回公司
老板开始给老婆打报告

张三请求报告
张三被开除了

四、动态代理

以上我们都是使用了静态代理,每次接口新增方法,那么其实现类都需要改动,JVM提供了动态代理的方式

1.创建动态代理Handler
package dynamicdelegate;

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

public class DynamicInvocationHandler implements InvocationHandler {
    private Function boss;

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (method.getName().equals("report")) {
            if (args[0] == null) {
                return null;
            }
            if (args[0].equals("老婆")) {
                return method.invoke(boss, args);
            } else {
                System.out.println(args[0] + "被开除了");
                return null;
            }
        }

        return method.invoke(boss, args);
    }

    /**
     * 设置被代理对象
     *
     * @param boss
     */
    public void setTarget(Function boss) {
        this.boss = boss;
    }
}

员工:

package dynamicdelegate.other;


import dynamicdelegate.Boss;
import dynamicdelegate.DynamicInvocationHandler;
import dynamicdelegate.Function;

import java.lang.reflect.Proxy;

public class Employee {
    public static void main(String[] args) {
        DynamicInvocationHandler handler = new DynamicInvocationHandler();
        Boss boss = new Boss();
        handler.setTarget(boss);

        Function proxy = (Function) Proxy.newProxyInstance(
                boss.getClass().getClassLoader(),
                boss.getClass().getInterfaces(),
                handler);

        proxy.report("老婆");
        proxy.report("张三");
    }
}

结果:
老板开始给老婆打报告
张三被开除了

2.动态代理原理

动态代理实际上是生成class字节码,根据InvocationHandler的invoke方法中业务逻辑,在Boss类中每个方法都相应的添加了业务逻辑后,生成了一个新的类

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值