ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

『设计模式』结构型 ——代理模式

2021-10-31 19:33:21  阅读:197  来源: 互联网

标签:角色 Object 代理 proxy rent 设计模式 public 结构型


代理模式是一种结构型设计模式, 让你能够提供对象的替代品或其占位符。 代理控制着对于原对象的访问, 并允许在将请求提交给对象前后进行一些处理。

静态代理

  • 抽象角色:一般会使用接口或者抽象类来解决
  • 真实角色:被代理的角色
  • 代理角色:代理着你是角色,代理真实角色后,我们一般会做一些复数操作
  • 客户:访问代理对象的人

以租房举例:

在这里插入图片描述

【抽象角色】

public interface Rent {
    public void rent();
}

【真实角色】

public class Host implements Rent{
    @Override
    public void rent() {
        System.out.println("房东要租房子了");
    }
}

【代理角色】

public class Agent implements Rent{
    private Host host;

    public Agent(Host host) {
        this.host = host;
    }

    public void seeHouse(){
        System.out.println("中介带你看房");
    }

    public void fare(){
        System.out.println("收中介费");
    }

    @Override
    public void rent() {
        host.rent();
    }
}

【客户】

public class Client {
    public static void main(String[] args) {
        Host host = new Host();
        Agent proxy = new Agent(host);
        proxy.seeHouse();
        proxy.rent();
        proxy.fare();
    }
}

输出结果:

中介带你看房
房东要租房子了
收中介费

代理模式的优点:

  • 可以使真实角色的操作哦更加纯粹,不用去关注一些公共的业务
  • 公共业务就交给代理角色,实现了业务的分工
  • 公共业务扩展的时候,方便集中管理

缺点

  • 一个真实角色就会产生一个代理角色,代码量会翻倍

动态代理

  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的
  • 动态代理分两大类:基于接口的动态代理基于类的动态代理
    • 基于接口:JDK 动态代理
    • 基于类:cglib
    • java 字节码实现:javasist

还是以租房为例:

JDK 动态代理

需要了解两个类:ProxyInvocationHandler

【代理角色】

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

// 这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {

    // 被代理的接口
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    // 动态生成代理对象
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
    }

    @Override
    // 处理代理实例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理中介带你看房");
        Object result = method.invoke(rent, args);
        System.out.println("收中介费");
        return result;
    }
}

【客户】

public class Client2 {
    public static void main(String[] args) {
        // 真实角色
        Host host = new Host();
        // 代理角色:现在还没有
        ProxyInvocationHandler pih = new ProxyInvocationHandler();

        // 通过调用程序处理角色来处理我们要调用的接口对象
        pih.setRent(host);

        // 生成代理类实例,即代理对象
        Rent proxy = (Rent) pih.getProxy();
        proxy.rent();
    }
}

通用动态代理处理类

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

public class ProxyHandler implements InvocationHandler {

    // 被动态代理的接口
    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }
	
    // 动态生成代理对象
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    @Override
    // 处理代理实例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // before call method do something
        Object result = method.invoke(target, args);
        // after call method do something

        return result;
    }
}

CGLib 动态代理

CGLib 采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。JDK 动态代理与 CGLib 动态代理均是实现 Spring AOP 的基础。

【jar包】

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.3.0</version>
</dependency>

【代理类】

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CGLibDynamicProxy implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

        if (method.getName().equals("rent")) {
            System.out.println("代理中介带你看房");
            methodProxy.invokeSuper(o, args);
            System.out.println("收中介费");
        }

        return null;
    }

    public Object getInstance(){
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Host.class); // 这里不需要搞个接口了,cglib支持基于类的动态代理
        enhancer.setCallback(this);
        return enhancer.create();
    }
}

【客户】

public class Client3 {
    public static void main(String[] args) {
        CGLibDynamicProxy proxy = new CGLibDynamicProxy();
        Rent rent = (Rent) proxy.getInstance();
        rent.rent();
    }
}

标签:角色,Object,代理,proxy,rent,设计模式,public,结构型
来源: https://blog.csdn.net/dreaming_coder/article/details/121068540

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有