首页 > 其他分享 >设计模式-代理模式

设计模式-代理模式

时间:2023-08-18 15:35:15浏览次数:43  
标签:String 代码 代理 模式 原始 login 设计模式 public

代理模式


(文章目录)


什么是代理模式

  代理模式(Proxy Design Pattern)的原理和代码实现都不难掌握。它在不改变原始类(或叫被代理类)代码的情况下,通过引入代理类来给原始类附加功能。


为什么要用代理模式

  • 职责清晰,功能增强部分代码可以放到代理类中,减少与业务代码的耦合;
  • 更符合开闭原则,对于修改的代码,放到代理类中,减少修改原有业务代码;

如何实现代理模式

静态代理

  预先将代理类编写好添加到工程中,而具体的实现方式又分为基于接口实现、基于继承实现,我们逐一进行讲解:

基于接口实现静态代理

  顾名思义,我们将原始类和代理类都实现同一接口来完成代理类中对原始类功能的增强。

// 接口
public interface ILoginService {
    String login(String userName, String passWord);
}

// 业务实现类
public class LoginService implements ILoginService{
    @Override
    public String login(String userName, String passWord) {
        System.out.println("校验用户名密码");
        return "ok";
    }
}

// 业务代理类
public class LoginServiceProxy implements ILoginService{
    private ILoginService iLoginService;

    public LoginServiceProxy(ILoginService iLoginService){
        this.iLoginService = iLoginService;
    }
    @Override
    public String login(String userName, String passWord) {

        System.out.println("代理类:执行校验前的操作");

        String login = this.iLoginService.login(userName, passWord);

        System.out.println("代理类:执行校验后的操作");

        return login;
    }
}

// 测试
public class TestProxy {
    public static void main(String[] args) {
        LoginService loginService = new LoginService();
        ILoginService iLoginService = new LoginServiceProxy(loginService);
        String login = iLoginService.login("", "");
    }
}

基于继承实现静态代理

  但是,如果原始类并没有定义接口,并且原始类代码并不是我们开发维护的(比如它来自一个第三方的类库),我们也没办法直接修改原始类,给它重新定义一个接口。在这种情况下,我们该如何实现代理模式呢?那么就需要用到我们接下来讲的采用继承的方式。让代理类继承原始类,然后扩展附加功能。代码示例如下:

public class LoginServiceProxy extends LoginService{

    @Override
    public String login(String userName, String passWord) {

        System.out.println("代理类:执行校验前的操作");

        String login = super.login(userName, passWord);

        System.out.println("代理类:执行校验后的操作");

        return login;
    }
}

动态代理

  静态代理很好实现,也很好理解,但是有一定的缺陷。一方面,我们需要在代理类中,将原始类中的所有的方法,都重新实现一遍,并且为每个方法都附加相似的代码逻辑。另一方面,如果要添加的附加功能的类有不止一个,我们需要针对每个类都创建一个代理类。如果有 50 个要添加附加功能的原始类,那我们就要创建 50 个对应的代理类。这会导致项目中类的个数成倍增加,增加了代码维护成本。并且,每个代理类中的代码都有点像模板式的“重复”代码,也增加了不必要的开发成本。   那这个问题怎么解决呢? 我们可以使用动态代理来解决这个问题。所谓动态代理(Dynamic Proxy),就是我们不事先为每个原始类编写代理类,而是在运行的时候,动态地创建原始类对应的代理类,然后在系统中用代理类替换掉原始类。那如何实现动态代理呢?


// 省略ILoginSerivce和LoginService的代码示例
...

// 动态创建代理类处理器
public class DynamicProxyHandler<T> implements InvocationHandler {
    private T proxiedObject;

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

    public T getProxy(){
        ClassLoader classLoader = proxiedObject.getClass().getClassLoader();
        Class<T>[] interfaceObjectArr = (Class<T>[]) proxiedObject.getClass().getInterfaces();
        return (T) Proxy.newProxyInstance(classLoader, interfaceObjectArr, this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("动态代理类:执行校验前的操作");
        Object result = method.invoke(proxiedObject, args);
        System.out.println("动态代理类:执行校验后的操作");
        return result;
    }
}

// 使用代理类
public class TestProxy {
    public static void main(String[] args) {
        ILoginService loginService = new LoginService();
        DynamicProxyHandler handler = new DynamicProxyHandler(loginService);
        ILoginService loginServiceDynamicProxy = (ILoginService) handler.getProxy();
        loginServiceDynamicProxy.login("","");
    }
}

  实际上,Spring AOP 底层的实现原理就是基于动态代理。用户配置好需要给哪些类创建代理,并定义好在执行原始类的业务代码前后执行哪些附加功能。Spring 为这些类创建动态代理对象,并在 JVM 中替代原始类对象。原本在代码中执行的原始类的方法,被换作执行代理类的方法,也就实现了给原始类添加附加功能的目的。


总结

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

标签:String,代码,代理,模式,原始,login,设计模式,public
From: https://blog.51cto.com/u_15322552/7137001

相关文章

  • CompositePattern-组合模式
    在C#中,组合模式(CompositePattern)是一种结构型设计模式,它允许您将对象组合成树状的结构,以表示部分-整体的层次关系,使得客户端可以以一致的方式处理单个对象和对象组合。在组合模式中,有以下几个角色:Component(组件):是组合中所有对象的通用接口,可以是抽象类或接口。它声明了一些操作......
  • 隧道代理被识别?爬虫编程的应对策略与解决方案
    没有遇到使用了隧道代理后,还是被网站识别到的问题?别急,今天我来分享一些解决识别问题的妙招!这些方法简单易行,让你的爬虫工作顺利进行,快来跟我一起看看吧!先了解一下,为什么爬虫使用隧道代理后仍然被识别?隧道代理是一种通过在本地计算机和目标服务器之间建立一个安全的隧道来隐藏真实IP......
  • 请解释自动装配模式的区别?
    在Spring框架中,自动装配是一种通过Spring容器在应用程序的不同组件之间自动建立依赖关系的机制。它简化了组件之间的配置工作,减少了手动设置依赖的繁琐步骤。Spring提供了几种自动装配模式,其中最常用的有三种:no、byType和byName。no(默认):这是默认的自动装配模式。它表示不进行自动......
  • X710网卡LACP模式下ifdown网卡后交换机侧依然处于UP状态,导致网络通信异常
    以下配置属于临时配置,重启后失效,具体建议在bios或者固件中解决。主要包含两个配置:1、使用ifdown命令关闭网卡无法使linkdown,交换机侧依然认为端口UP进行流量转发,无法正常通信2、在某些环境中,LACP可能无法正常工作,这些环境要求将包含LCAP信息的LLDP帧转发到网络堆栈。#查看网卡......
  • Springboot中实现观察者模式
    在SpringBoot中实现观察者模式可以通过以下步骤进行:1.定义观察者接口(Observer):创建一个接口,定义观察者对象需要实现的方法,例如update()方法。publicinterfaceObserver{voidupdate();}2.实现具体的观察者(具体实现Observer接口的类):创建一个或多个具体的观察者类,实......
  • 医疗信息云LIS系统源码 .Net Core版SaaS模式
    SaaS模式.NetCore版云LIS系统源码医疗信息LIS系统是专为医院检验科设计的一套实验室信息管理系统,能将实验仪器与计算机组成网络,使病人样品登录、实验数据存取、报告审核、打印分发,实验数据统计分析等繁杂的操作过程实现了智能化、自动化和规范化管理。有助于提高实验室的整体管理......
  • 设计模式(二)工厂方法
    一、前言工厂模式常见的词:简单工厂、工厂方法、抽象工厂。简单工厂不属于23种经典设计模式,但通常将它作为学习其他工厂模式的基础。二、简单工厂1、定义定义一个工厂类,它可以根据参数的不同返回不同类型的实例,被创建的实例通常都具有共同的父类。由于简单的工厂模式中用于创建......
  • 一文带你读懂设计模式之责任链模式 | 京东云技术团队
    1.前言emm,翻了一下之前刚入职时候的学习笔记,发现之前在熟悉业务代码的时候曾经专门学习并整理过过设计模式中的责任链模式,之前只是对其简单了解过常用的设计模式有哪些,并未结合实例和源码深入对其探究,利用熟悉代码契机进行系统学习并整理文档如下。2.什么是责任链模式?俗话说没有规......
  • 代理IP与Socks5代理:跨界电商战略中的智能引擎与数据安全壁垒
    一、代理IP与Socks5代理的概述代理IP简介:代理IP技术允许企业通过中间服务器进行数据访问,隐藏真实IP地址,规避网站的访问限制。Socks5代理简介:Socks5代理是IP代理的一种,支持TCP和UDP协议,具备更高的性能和安全性,适用于多种数据传输场景。二、数据采集中的应用与优势跨界电商的数据需......
  • 7种创建方式,带你理解Java的单例模式
    本文分享自华为云社区《《Java极简设计模式》第01章:单例模式(Singleton)》,作者:冰河。单例设计模式看几个单例对象的示例代码,其中有些代码是线程安全的,有些则不是线程安全的,需要大家细细品味,这些代码也是在高并发环境下测试验证过的。代码一:SingletonExample1这个类是懒汉模式......