设计模式:代理模式

本文介绍了代理模式作为结构型设计模式的一种,用于对象间的协调以实现代码解耦。代理模式常用于添加如监控、统计等非功能性需求,保持业务代码的纯粹。文中通过静态代理的实例展示了如何实现代理模式,并提到了动态代理和特殊情况下的代理实现,如继承和强制代理。同时,区分了代理模式与装饰器模式的区别。
摘要由CSDN通过智能技术生成
设计模式类别

我们之前一直弄的单例,工厂,原型还有建造者模式,都是创建型模式,就是都是针对对象的创建来设计的。

我们这边的代理模式是结构型模式,这种模式不用担心什么对象创建的,而是用来多个对象如何相互配合组成合适的结构来实现代码的解耦的设计模式,引入这个概念后,每当我们来一个新的设计模式都会说他属于什么类似的设计模式。

这种设计模式类别一共就三种,前者我们常见的创建型设计模式,还有结构型设计模式和行为型设计模式。

代理模式
代理模式的基本知识

代理模式可以对比我们所说的中介或者说中间商,我们不用中间商可不可以买车,买房这些,那一定是可以的,但是由于我们受到时间,资源等实际情况限制导致我们,只能减少其他的成本借助中介,来做我们的代理,去买房买车。

对比我们的代码,就是我们希望我们的业务代码更加的集中业务方面,不要掺杂其他的东西,比如说日志,发送消息,审批流这些扩展类的,类似AOP,AOP就是代理的一个非常有代表性的例子。

代理模式应用场景很多:代理模式最常用的一个应用场景就是,在业务系统中开发一些非功能性需求,比如:监控、统计、鉴权、限流、事务、幂等、日志。我们将这些附加功能与业务功能解耦,放到代理类中统一处理,让程序员只需要关注业务方面的开发。

代理模式还可以用在 RPC、缓存等应用场景中

在这里插入图片描述

代理的原理和组成

通过上个图,基本就说明了代理的组成部分,主题,实现主题,和代理类。

一般来说经典的静态代理模式一般来说是:主题是一个接口,实现主题,和代理类都是来实现这个接口的,那怎么样去使用代理呢?很简单,当client调用的时候调用代理类,代理类的构建方法是由实现主题来构成的,我们就可以代理。

我的github实现代码

大致如下
主题

package com.example.test.proxy.normal;

/**
 * @Author: zhangpeng
 * @Description:  静态代理:买房子的抽象主题 subject
 * @Date: 2022/6/8
 */
public interface HouseService {

    public void saleHouse();
}

实现主题

package com.example.test.proxy.normal;

/**
 * @Author: zhangpeng
 * @Description:  静态代理:买房子这个实际业务的实现主题subjext
 * @Date: 2022/6/8
 */
public class HouseServiceImpl implements HouseService{
    @Override
    public void saleHouse() {
        System.out.println("-----------买房子的具体业务start------------");
        System.out.println("审查资格");
        System.out.println("贷款");
        System.out.println("房票,验收,拿钥匙");
        System.out.println("-----------买房子的具体业务end------------");
    }
}

代理类

package com.example.test.proxy.normal;

/**
 * @Author: zhangpeng
 * @Description:
 * @Date: 2022/6/8
 */
public class ProxyHouseAgent implements HouseService {

    //具体主题要被代理起来
    private HouseServiceImpl houseServiceImpl;


    public ProxyHouseAgent (HouseServiceImpl houseService){
         this.houseServiceImpl = houseService;
    }

    @Override
    public void saleHouse() {
        System.out.println("带你看房-----------");
        System.out.println("你很满意");
        houseServiceImpl.saleHouse();
        System.out.println("佣金到手,哈哈哈");
    }
}

我们的client使用如下

package com.example.test.proxy.normal;

/**
 * @Author: zhangpeng
 * @Description:
 * @Date: 2022/6/8
 */
public class HouseTest {
    public static void main(String[] args) {

           HouseService houseService = new ProxyHouseAgent(new HouseServiceImpl());
           houseService.saleHouse();

    }
}
其他特殊的代理模式

代理模式非常常用,但是有时候有些情况会有特殊要求,比如说我们想通过扩展第三方功能来代理,但是我们又不能修改第三方模块,也就是不能通过接口来实现代理模式扩展,那我们可以通过继承的方式来实现
示例代码:
关于通过继承来实现代理

还有就是强制代理,就是这些方法只能通过代理才能调用,不能直接去使用实现主题。

除了这些,最大的代理模式其实是动态代理,Java的动态代理是通过反射,AOP就是一种非常不错的范例。别的语言实际上也可以,但是没有Java这么方便,可能要自己先实现自己的反射才行,或者要动态指针改变来完成。

这里是一个关于Java的代理类的实现代码
这里主要的还是内部类实现了InvocationHandler ,然后根据创建的代理类代理参数传递过来的参数。


public class MetricsCollectorProxy {
  private MetricsCollector metricsCollector;

  public MetricsCollectorProxy() {
    this.metricsCollector = new MetricsCollector();
  }

  public Object createProxy(Object proxiedObject) {
    Class<?>[] interfaces = proxiedObject.getClass().getInterfaces();
    DynamicProxyHandler handler = new DynamicProxyHandler(proxiedObject);
    return Proxy.newProxyInstance(proxiedObject.getClass().getClassLoader(), interfaces, handler);
  }

  private class DynamicProxyHandler implements InvocationHandler {
    private Object proxiedObject;

    public DynamicProxyHandler(Object proxiedObject) {
      this.proxiedObject = proxiedObject;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      long startTimestamp = System.currentTimeMillis();
      Object result = method.invoke(proxiedObject, args);
      long endTimeStamp = System.currentTimeMillis();
      long responseTime = endTimeStamp - startTimestamp;
      String apiName = proxiedObject.getClass().getName() + ":" + method.getName();
      RequestInfo requestInfo = new RequestInfo(apiName, responseTime, startTimestamp);
      metricsCollector.recordRequest(requestInfo);
      return result;
    }
  }
}

//MetricsCollectorProxy使用举例
MetricsCollectorProxy proxy = new MetricsCollectorProxy();
IUserController userController = (IUserController) proxy.createProxy(new UserController());

PS:
代理模式和装饰器模式,但从静态代理上看二者差不多,从使用上理解就是代理就是添加功能,装饰器模式是功能的加强。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值