系列文章目录
(其他设计模式可以参考 👉👉👉)设计模式_小杰不秃头的博客 😊😄😛
前言
今天继续给大家介绍23种设计模式中的代理模式,熟悉Spring的小伙伴都知道,Aop使用的就是代理模式,所以,代理模式还是非常重要的,在工作中用的也是非常的多。🌈
一、代理模式
代理模式(Proxy Pattern)是面向对象编程 中的一种设计模式,它为其他对象提供一个代理 或占位符 ,以控制对这个对象的访问。代理对象在客户端 和目标对象 之间起到中介 的作用,客户端并不直接与目标对象交互,而是通过代理对象 来间接调用目标对象的方法。(简单理解就是"房子中介"的一个角色)
特点
- 中介作用:代理对象作为客户端和目标对象之间的中介,可以拦截或修改客户端对目标对象的请求。
- 功能增强:可以在不修改目标对象代码的前提下,通过代理对象为目标对象增加额外的功能。如:Spring中的AOP
- 控制访问:代理对象可以控制对目标对象的访问,比如检查权限、记录日志、实现延迟加载等。
举一个简单的例子帮助大家理解,假如说你想买一个房子,但是你没有时间去挑选,所以你就找了一个房子中介帮你去找房子,这个过程就是一个代理的过程,房子中介就是一个代理对象。
二、静态代理
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;
}
@Override
public String toString() {
return "Order{" +
"info='" + info + '\'' +
", userId='" + userId + '\'' +
'}';
}
}
创建持久层的接口和实现类
java
public interface OrderDao {
int insertOrder(Order order);
}
public class OrderDaoImpl implements OrderDao {
@Override
public 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;
@Override
public 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("动态代理对象...开启事务...");
}
@Override
public 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'}
动态代理对象...提交事务...
*/
总结
总结来说,静态代理和动态代理各有优缺点,适用于不同的场景。静态代理适用于接口稳定、功能较为简单的场景,而动态代理则适用于需要灵活代理任意实现了接口的类的场景。