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

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 【结构型设计模式】代理模式,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

一、基本概念

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();
    }
}

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

如有错误,欢迎指正

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/136818.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!