【设计模式】之代理模式(两种)

devtools/2024/10/18 8:01:30/

系列文章目录

(其他设计模式可以参考 👉👉👉)设计模式_小杰不秃头的博客  😊😄😛


前言

今天继续给大家介绍23种设计模式中的代理模式,熟悉Spring的小伙伴都知道,Aop使用的就是代理模式,所以,代理模式还是非常重要的,在工作中用的也是非常的多。🌈


一、代理模式

代理模式(Proxy Pattern)面向对象编程中的一种设计模式,它为其他对象提供一个代理占位符,以控制对这个对象的访问。代理对象在客户端目标对象之间起到中介的作用,客户端并不直接与目标对象交互,而是通过代理对象来间接调用目标对象的方法。(简单理解就是“房子中介”的一个角色)

特点

  1. 中介作用:代理对象作为客户端和目标对象之间的中介,可以拦截或修改客户端对目标对象的请求。
  2. 功能增强:可以在不修改目标对象代码的前提下,通过代理对象为目标对象增加额外的功能。如:Spring中的AOP
  3. 控制访问:代理对象可以控制对目标对象的访问,比如检查权限、记录日志、实现延迟加载等。

举一个简单的例子帮助大家理解,假如说你想买一个房子,但是你没有时间去挑选,所以你就找了一个房子中介帮你去找房子,这个过程就是一个代理的过程,房子中介就是一个代理对象。

二、静态代理

1、静态代理定义和特点

静态代理(Static Proxy):是在程序编译时确定代理类的代码,代理类和目标类实现了相同的接口。静态代理的实现相对简单,代理对象和目标对象实现相同的接口,客户端通过代理对象调用目标对象的方法。

特点:静态代理需要手动编写代理类的代码,因此当接口发生变化时,代理类也需要相应地修改。由于代理类在编译期间就已经确定,因此性能相对较高。但是,静态代理只能为给定接口的实现类做代理,如果接口不同则需要重新定义不同的代理类。

2、使用场景

使用场景:静态代理通常用于为一些功能较为简单的类提供代理,如增加日志记录、性能监控等功能。由于静态代理需要手动编写代理类的代码,因此它通常适用于接口稳定、功能较为简单的场景。

3、静态代理的简单实现

这里举一个比较粗糙的例子,模拟插入订单的这个业务场景。

跟我们平时开发的一样,首先创建实体类Order

java">public class Order {private String info;private String userId;public String getInfo() {return info;}public void setInfo(String info) {this.info = info;}public String getUserId() {return userId;}public void setUserId(String userId) {this.userId = userId;}@Overridepublic String toString() {return "Order{" +"info='" + info + '\'' +", userId='" + userId + '\'' +'}';}
}

创建持久层的接口和实现类

java">public interface OrderDao {int insertOrder(Order order);
}public class OrderDaoImpl implements OrderDao {@Overridepublic int insertOrder(Order order) {System.out.println("持久层...插入订单..."+order.toString());return 1;}
}

创建服务层的接口和实现类

java">public interface OrderService {int insertOrder(Order order);
}public class OrderServiceImpl implements OrderService {private OrderDao orderDao;@Overridepublic int insertOrder(Order order) {orderDao = new OrderDaoImpl();System.out.println("业务层...调用持久层insertOrder方法...");return orderDao.insertOrder(order);}
}

关键一步,创建静态代理对象

java">public class OrderServiceImplStaticProxy {private OrderService orderService;public int insertOrder(Order order){before();orderService = new OrderServiceImpl();int result = orderService.insertOrder(order);after();return result;}private void after() {System.out.println("静态代理对象...提交事务...");}private void before() {System.out.println("静态代理对象...开启事务...");}
}

测试

java">public class Test {public static void main(String[] args) {Order order = new Order();order.setInfo("xxxx笔记本电脑");order.setUserId("1");OrderServiceImplStaticProxy proxy = new OrderServiceImplStaticProxy();proxy.insertOrder(order);}
}/*打印结果:
静态代理对象...开启事务...
业务层...调用持久层insertOrder方法...
持久层...插入订单...Order{info='xxxx笔记本电脑', userId='1'}
静态代理对象...提交事务...
*/

三、动态代理

1、动态代理定义和特点

 动态代理(Dynamic Proxy)是在程序运行过程中通过反射机制动态生成代理类的代码,实现对目标类的代理访问。动态代理可以代理任意实现了接口的类,不受接口的限制。

特点:动态代理可以根据具体需求动态生成代理类,避免了手动编写代理类的繁琐工作,方便接口的扩展和修改。由于动态代理在程序运行时生成代理类的代码,因此性能较静态代理略低。但是,动态代理的灵活性 更高,可以代理任意实现了接口的类。

2、使用场景

使用场景动态代理广泛应用于各种场景,包括但不限于AOP(面向切面编程)、远程方法调用、RPC(远程 过程调用)等。通过动态代理,我们可以实现对目标方法的拦截和增强,将系统的横切关注点(如日志记录、性能统计等)与业务逻辑代码进行解耦,提高代码的可维护性和可扩展性。

3、动态代理的简单实现

这里例子还以插入订单为例,其他都不变,只需将静态代理换为动态代理就可。

java">public class OrderServiceImplDynamicProxy implements InvocationHandler {private Object orderService;public OrderServiceImplDynamicProxy(Object service){this.orderService = service;}public Object bind(){//创建动态代理对象return Proxy.newProxyInstance(orderService.getClass().getClassLoader(), orderService.getClass().getInterfaces(),this);}private void after() {System.out.println("动态代理对象...提交事务...");}private void before() {System.out.println("动态代理对象...开启事务...");}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {before();Object o = method.invoke(orderService, args);after();return o;}
}

测试

java">public class Test {public static void main(String[] args) {OrderService service = (OrderService)new OrderServiceImplDynamicProxy(new OrderServiceImpl()).bind();Order order = new Order();order.setInfo("xxx手机");order.setUserId("2");service.insertOrder(order);}
}/*打印结果:
动态代理对象...开启事务...
业务层...调用持久层insertOrder方法...
持久层...插入订单...Order{info='xxx手机', userId='2'}
动态代理对象...提交事务...
*/


总结

总结来说,静态代理和动态代理各有优缺点,适用于不同的场景。静态代理适用于接口稳定、功能较为简单的场景,而动态代理则适用于需要灵活代理任意实现了接口的类的场景。


http://www.ppmy.cn/devtools/41202.html

相关文章

Java网络编程之TCP协议核心机制(一)

目录 题外话 正题 TCP协议核心机制 1.确认应答机制 2.超时重传 3.连接管理 三次握手(建立数据连接)和四次挥手(断开连接) 三次握手 三次握手的意义 为什么不能是四次挥手和两次挥手呢??? 四次挥手(断开连接) 四次挥手的意义 四次挥手能变为三次挥手吗? 小结 题…

Spring AOP切面实现为mapper层指定方法入参字段赋值

需求: 有时候我们在进行某些操作时,可能需要额外进行复制操作,而这些字段往往不是由前端/客户端填写输入的,而是由后端给与,类似于 登陆者、创建时间、更新时间等字段,这时,可以借助AOP指定mapp…

编程最佳实践-卫函数

文章目录 卫函数要解决什么问题?什么是卫函数正确使用卫函数的心法卫函数推荐使用场景检查输入参数处理特殊情况减少嵌套 卫函数不推荐使用场景示例 卫函数要解决什么问题? 卫函数主要解决的是if嵌套太深导致的代码可读性差的问题。实际开发场景中大家都…

RK3588 usb adb调试

问题:2路usb3.0 otg,在使用其中一路typeC1作用adb功能使用后,将这路设置成host模式后,另外一路typeC0设置device,这路还是无法当做usb adb来使用。 查看usb typeC1当前模式 cat /sys/kernel/debug/usb/fc400000.usb/m…

uniapp引入vant组件库

在 UniApp 中引入 Vant 组件库的完整步骤通常如下: 安装 Vant: 首先,你需要通过 npm 或 yarn 安装 Vant。打开项目的根目录,然后在命令行中执行以下命令: 使用 npm: npm install vant 或者使用 yarn&…

docker 和 docker-compose

Docker是一种开源的容器化平台,它可以帮助开发人员将应用程序及其所有依赖项打包到一个独立的、可移植的容器中。这意味着您可以在任何地方运行Docker容器,而不需要担心环境差异或依赖项的问题。 Docker Compose是Docker官方提供的一个工具,…

Kubernetes中的RBAC

目录 1. Role2. ClusterRole3. RoleBinding4. ClusterRoleBinding5.启用 RBAC Kubernetes中的RBAC(Role-Based Access Control,基于角色的访问控制)是一种机制,用于控制集群内资源的访问权限。RBAC允许管理员通过定义角色&#xf…

杰发科技AC7801——ADC之Bandgap和内部温度计算

0. 参考 电流模架构Bandgap设计与仿真 bandgap的理解(内部带隙电压基准) ​ ​ 虽然看不懂这些公式,但是比较重要的一句应该是这个:因为传统带隙基准的输出值为1.2V ​ 1. 使用 参考示例代码。 40002000是falsh控制器寄…