【结构型设计模式】代理模式

一、基本概念

1、核心作用:

  • 通过代理,控制对对象的访问。
    可以详细控制访问某个(某类)对象的方法,在调用这个方法前做前置处理,在调用这个方法后做后置处理(即AOP的微观实现)

2、核心角色:

  • 抽象角色:
    定义代理角色和真实角色的公共对外方法
  • 真实角色:
    实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用
    只需要关注真正的业务逻辑
  • 代理角色:
    实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并且可以附加自己的操作
    将统一的流程控制放到代理角色中处理

3、分类(根据代理创建时期的不同分为静态代理和动态代理)

  • 静态代理(静态定义代理类)
    静态代理由开发人员或特定工具自动生成源代码,再对其编译,在程序运行前 ,代理类已经生成
  • 动态代理(动态生成代理类)
    动态代理在程序运行时,利用java的反射机制动态创建而成

4、结合实例
假如我们请明星参加商演,明星就相当于这里的真实角色,他的经纪人就相当于这里的代理角色,经纪人在请明星唱歌(即访问这个对象)前,需要负责签合同和订机票等(前置处理),唱歌之后负责收尾款(后置处理),我们作为客户只和他的经纪人打交道即可

二、静态代理

// 抽象角色
public interface Star {
    /**
     * 签合同
     */
    void signContract();

    /**
     * 订机票
     */
    void bookTicket();

    /**
     * 唱歌
     */
    void sing();

    /**
     * 收尾款
     */
    void collectMoney();
}

// 真实角色
public class RealStar implements Star{
    @Override
    public void signContract() {
        System.out.println("陈奕迅signContract");
    }

    @Override
    public void bookTicket() {
        System.out.println("陈奕迅bookTicket");
    }

    @Override
    public void sing() {
        System.out.println("陈奕迅sing");
    }

    @Override
    public void collectMoney() {
        System.out.println("陈奕迅collectMoney");
    }
}
// 代理角色(提供对真实角色的代理访问)
public class ProxyStar implements Star{
    // 引入真实角色
    private Star star;

    public ProxyStar(Star star) {
        this.star = star;
    }

    @Override
    public void signContract() {
        System.out.println("经纪人signContract");
    }

    @Override
    public void bookTicket() {
        System.out.println("经纪人bookTicket");
    }

    @Override
    public void sing() {
        star.sing();
    }

    @Override
    public void collectMoney() {
        System.out.println("经纪人collectMoney");
    }
}

代码运行结果为
在这里插入图片描述

三、动态代理

1、相较于静态代理的优点:

静态代理中,如果我们要代理多个方法,那么在代理类中,我们需要声明多个方法,例如上面ProxyStar类中,经纪人想代理bookTicket()方法,那么就需要在他重写的对应方法中调用真实对象的bookTicket()方法,这样比较繁琐

而在动态代理模式中,抽象角色中声明的所有方法都被转移到调用处理器一个集中的方法invoke()中处理,这样我们可以更加统一和灵活处理众多方法

一个动态代理可以代理多个类,代理的是接口!

2、JDK自带的动态代理对象

java.lang.reflect.Proxy
作用:动态生成代理类和对象

java.lang.reflect.InvocationHandler(处理器接口)
可以通过对invoke接口实现对真实对象的代理访问,可以在这里做统一的流程控制
每次通过Proxy生成代理类对象时,都要指定对应的处理器对象

// 抽象角色
public interface Star {
    /**
     * 签合同
     */
    void signContract();

    /**
     * 订机票
     */
    void bookTicket();

    /**
     * 唱歌
     */
    void sing();

    /**
     * 收尾款
     */
    void collectMoney();
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

// 处理器对象
public class StarHandler implements InvocationHandler {
    Star realStar;

    public StarHandler(Star star) {
        this.realStar = star;
    }

	// proxy:代理对象  method:代理类中调用invoke处理程序的方法对象  args:method方法所需要的参数
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object obj = null;

        // 在此处进行统一的前置处理,这就是AOP的核心原理
        System.out.println("签合同、订机票");
        if (method.getName().equals("sing")) {
            obj = method.invoke(realStar, args);
        }

        // 在此处进行统一的后置处理
        System.out.println("付尾款");
        return obj;
    }
}
// 真实角色
public class RealStar implements Star {
    @Override
    public void signContract() {
        System.out.println("陈奕迅signContract");
    }

    @Override
    public void bookTicket() {
        System.out.println("陈奕迅bookTicket");
    }

    @Override
    public void sing() {
        System.out.println("陈奕迅sing");
    }

    @Override
    public void collectMoney() {
        System.out.println("陈奕迅collectMoney");
    }
}
import java.lang.reflect.Proxy;

public class Client {
    public static void main(String[] args) {
        Star realStar = new RealStar();
        StarHandler starHandler = new StarHandler(realStar);
        
        // 第一个参数是类加载器,第二个参数是代理类的抽象角色,第三个参数是实现InvocationHandler接口的对象实例
        Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Star.class}, starHandler);
		// 每个方法的实现细节都是调用了starHandler对象的invoke方法
        proxy.sing();
    }
}

代码运行结果为
在这里插入图片描述

如有错误,欢迎指正

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值