06设计模式-代理模式

Posted wfdespace

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了06设计模式-代理模式相关的知识,希望对你有一定的参考价值。

1.5.深入分析代理模式

1.5.1.深度分析代理模式【上】

时长:46min

学习目标

  》代理模式的应用场景及实现原理

  》区分静态代理与动态代理

  》cglib和jdk Proxy实现动态代理的区别

  》手写实现定义的动态代理

  》spring Aop基于动态代理,打下基础

5.1.代理模式定义

5.1.1.什么是代理模式?

  Proxy Pattern,是指为其他对象提供一种代理,以控制对这个对象的访问。

  代理对象,在客户端与目标对象之间起到中介作用,起到功能增强的作用。

  属于结构型设计模式。

 

代理之生活理解:

  可以参照中介来理解。如:租房中介,用户需要租房子,但是找不到或没时间找房子【用户功能不够强大】,那么,

就找到一个代理【中介】,中介是专门找到房子的【他的功能比用户强大】,最后中介帮用户找到了房子。

  所以,代理是对目标对象【用户】功能的增强。

 

生活中代理场景:

  房产中介,快递小哥,黄牛党。

  

5.1.2.代理模式的适用场景

》保护目标对象

》增强目标对象

5.2.代理模式的实现示例代码

5.2.1.通用写法

5.2.1.1.目标对象定义

  由于面向接口编程,定义顶层接口:

package com.wf.proxy.general;

/**
 * @ClassName ISubject
 * @Description 目标对象的抽象接口
 * @Author wf
 * @Date 2020/5/15 17:00
 * @Version 1.0
 */
public interface ISubject {
    void request();
}

目标对象实现:

package com.wf.proxy.general;

/**
 * @ClassName RealSubject
 * @Description 目标对象
 * @Author wf
 * @Date 2020/5/15 17:02
 * @Version 1.0
 */
public class RealSubject implements ISubject {
    @Override
    public void request() {
        System.out.println("目标对象真实的服务实现");
    }
}
5.2.1.2.代理类定义
package com.wf.proxy.general;

/**
 * @ClassName Proxy
 * @Description 代理对象
 * @Author wf
 * @Date 2020/5/15 17:05
 * @Version 1.0
 */
public class Proxy implements ISubject {
    //代理对象 需要对目标对象的功能进行增强
    //即增强目标对象的方法,所以实现同一接口
    //增强目标对象,所以个课程目标对象【基于多态,可以引入顶层接口bean】
    private ISubject subject;
    
    //客户端要传参目标对象,这里定义构建器传参
    public Proxy(ISubject subject) {
        this.subject = subject;
    }

    //程序中,什么叫功能增强,就是多加一段代码,提供更多功能
    @Override
    public void request() {
        doBefore();
        //方法前增强
        subject.request();
        //方法后增强
        doAfter();
    }

    private void doAfter() {
        System.out.println("方法后面进行增强");
    }

    private void doBefore() {
        System.out.println("方法前面进行增强");
    }
}
5.2.1.3.客户端调用
package com.wf.proxy.general;


/**
 * @ClassName Client
 * @Description 客户端调用
 * @Author wf
 * @Date 2020/5/15 17:15
 * @Version 1.0
 */
public class Client {
    public static void main(String[] args) {
        RealSubject subject = new RealSubject();
        Proxy proxy = new Proxy(subject);
        proxy.request();
    }
}

测试结果如下:

技术图片

 

 说明:

  显然,request方法的功能得到了增强。

5.2.1.4.系统类图

技术图片

 

5.3.静态代理与动态代理

5.3.1.什么是静态代理?

  先以一个生活场景,通过代码来说明。

  程序员平时加班较多,没时间找对象-----------父母着急,帮忙物色对象【充当代理】,安排相亲-------最后找到女朋友。

  抽象出业务模型

  Person----Parent-----------findLove

5.3.1.1.代码示例
1.定义顶层接口
package com.wf.proxy.staticproxy;

/**
 * @ClassName IPerson
 * @Description 程序员顶层抽象接口
 * @Author wf
 * @Date 2020/5/15 17:31
 * @Version 1.0
 */
public interface IPerson {
    void findLove();
}
2.目标对象
package com.wf.proxy.staticproxy;

/**
 * @ClassName Person
 * @Description 程序员 目标对象
 * @Author wf
 * @Date 2020/5/15 17:33
 * @Version 1.0
 */
public class Person implements IPerson {
    @Override
    public void findLove() {
        System.out.println("程序员,自己没有找到女朋友");
    }
}
3.代理类---父母
package com.wf.proxy.staticproxy;

/**
 * @ClassName ParentProxy
 * @Description 父母 代理类
 * @Author wf
 * @Date 2020/5/15 17:36
 * @Version 1.0
 */
public class ParentProxy implements IPerson {
    private IPerson person;

    public ParentProxy(IPerson person) {
        this.person = person;
    }

    @Override
    public void findLove() {
        //
        System.out.println("开始帮儿子,物色对象");
        person.findLove();
        System.out.println("儿子说,ok,开始交往");
    }
}
4.客户端代码
package com.wf.proxy.staticproxy;

/**
 * @ClassName Client
 * @Description 客户端调用类
 * @Author wf
 * @Date 2020/5/15 17:41
 * @Version 1.0
 */
public class Client {
    public static void main(String[] args) {
        Person person = new Person();
        ParentProxy proxy = new ParentProxy(person);
        proxy.findLove();
    }
}

测试结果如下:

技术图片

 

 说明:

  因为有大量人可能也没有找到对象,针对这种需求,社会上形成一个产业链,叫婚介所,婚恋网。

  因此,系统需要扩展

 

  但是,张三的父母,力量有限,只能给儿子一个人物色对象。

  如果李四也想找到张三的父母物色对象,就没办法完成。也就是父母这个代理只能代理儿子的事情。

  这就是静态代理。

 

  如果想要为更多人做代理,代理需要更为强大,于是,产生动态代理

 

静态代理:

  只能代理某特定的目标对象。如:房产中介,只能代理租客。

 

动态代理:

  代理对象可以代理任意的目标对象。

5.3.2.动态代理的实现

  在java中,动态代理有两种实现方案:

 》jdk Proxy代理类实现

 》cglib库实现

5.3.2.1.jdk实现动态代理
1.婚介所代理类创建
package com.wf.proxy.dynamicproxy.jdkproxy;

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

/**
 * @ClassName MarriageAgency
 * @Description 婚介所 代理类
 * @Author wf
 * @Date 2020/5/15 18:23
 * @Version 1.0
 */
public class MarriageAgency implements InvocationHandler {
    //jdk动态代理 实现一个抽象的接口【接口可以定义任意功能】

    //加强目标对象功能,需要引入目标对象
    private IPerson person;

    public IPerson getProxy(IPerson person) {
        this.person = person;
        //根据目标对象,得到代理对象
        //jdk底层是基于字节码,需要传参代理类的类加载器,并且代理对象需要实现接口功能【传参接口,实例this】
        Class<? extends IPerson> personClass = person.getClass();
        return (IPerson)Proxy.newProxyInstance(personClass.getClassLoader(), personClass.getInterfaces(),this);
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //加强目标对象的方法
        doBefore();
        Object result = method.invoke(this.person, args);
        doAfter();
        return result;
    }

    private void doAfter() {
        System.out.println("是不是确认关系,开始交往");
    }

    private void doBefore() {
        System.out.println("开始物色对象");
    }
}
2.顶层接口类
package com.wf.proxy.dynamicproxy.jdkproxy;

/**
 * @ClassName IPerson
 * @Description 程序员顶层抽象接口
 * @Author wf
 * @Date 2020/5/15 17:31
 * @Version 1.0
 */
public interface IPerson {
    void findLove();
}

 

以上是关于06设计模式-代理模式的主要内容,如果未能解决你的问题,请参考以下文章

Java设计模式学习06——静态代理与动态代理(转)

Java RMI地址解析问题

Java 设计模式之代理模式,Java 静态代理,Java 动态代理

java代码实现设计模式之代理模式

用于从 cloudkit 检索单列的代码模式/片段

设计模式----代理模式