设计模式-代理模式

写在前面

Hello,我是易元,这篇文章是我学习设计模式时的笔记和心得体会。如果其中有错误,欢迎大家留言指正!

初期实现

系统背景与设计目标

电商平台需快速上线用户登录功能,初期核心需求包括:

  1. 用户身份验证(login
  2. 用户信息查询(getUserById

开发团队采用直接实现模式,在10个工作日内交付了基础功能。

初始代码结构

1. 抽象接口定义
arduino 复制代码
public interface UserService {  
    void login(String username, String password);  
    String getUserById(Integer userId);  
}  
2. 核心业务实现
typescript 复制代码
class UserServiceImpl implements UserService {  
    @Override  
    public void login(String username, String password) {  
        System.out.println("验证用户:" + username + " 登录成功");  
    }  

    @Override  
    public String getUserById(Integer userId) {  
        return "用户ID:" + userId + " 的详细信息";  
    }  
}  
3. 测试验证
makefile 复制代码
验证用户:admin 登录成功  
用户ID:1 的详细信息  

需求变更:安全与审计要求

系统上线3个月后,安全团队提出新需求:
权限分级 :仅允许admin用户执行登录操作
操作审计:记录所有敏感操作的执行日志

快速实现方案

typescript 复制代码
public class UserServiceImpl implements UserService {  
    @Override  
    public void login(String username, String password) {  
        // 硬编码权限校验  
        if (!"admin".equals(username)) {  
            System.out.println("无访问权限!");  
            return;
        }

        System.out.println("验证用户:" + username + " 登录成功");
        System.out.println("[日志] 用户登录操作: " + username); // 日志耦合
    }  
}  

架构隐患分析

问题现象 潜在风险
业务逻辑包含权限校验代码 修改权限策略需重新部署核心服务
日志记录散落在各个方法 新增日志字段需修改所有业务方法
功能扩展需修改既有实现 20%业务代码+80%辅助代码的维护困境

第二话:代理模式重构实践

重构目标

  1. 关注点分离:业务代码仅处理用户验证/信息查询
  2. 非侵入扩展:新增功能不修改原有实现类
  3. 标准化接入:权限、日志等模块可插拔替换

代理模式三大核心

角色 职责说明 案例对应
Subject 定义业务接口规范 UserService 接口
RealSubject 实现核心业务逻辑 UserServiceImpl
Proxy 控制访问并增强功能 UserServiceProxy 代理类

静态代理实现方案

代理类结构
typescript 复制代码
public class UserServiceProxy implements UserService {  
    private final UserService realService;  

    public UserServiceProxy(UserService realService) {  
        this.realService = realService;  
    }  

    @Override  
    public void login(String username, String password) {  
        checkPermission(username);          // 前置增强  
        realService.login(username, password);  
        logOperation("login", username);    // 后置增强  
    }  

    // 权限校验模块化  
    private void checkPermission(String username) {  
        if (!"admin".equals(username))  
            throw new SecurityException("权限验证失败");  
        System.out.println("✅ 权限校验通过");  
    }  

    // 日志记录标准化  
    private void logOperation(String operation, String params) {  
        System.out.printf("[AUDIT] %s - params: %s%n", operation, params);  
    }  
}  

测试验证与执行效果
typescript 复制代码
public class ProxyTest {  
    public static void main(String[] args) {  
        UserService service = new UserServiceProxy(new UserServiceImpl());  
        service.login("admin", "123456");  
        System.out.println(service.getUserById(1));  
    }  
}  

输出结果

csharp 复制代码
✅ 权限校验通过  
验证用户:admin 登录成功  
[AUDIT] login - params: admin  
用户ID:1 的详细信息  

架构演进对比

维度 初始实现 代理模式实现
代码结构 业务与辅助逻辑混杂 业务/辅助逻辑分层
维护成本 修改1个功能需改动所有相关方法 新增代理类即可扩展功能
测试难度 需模拟完整环境测试耦合逻辑 可独立测试业务类和代理类
扩展性 新增功能导致类膨胀 符合开闭原则,通过组合实现功能增强

长话短说

设计本质

通过中间层代理实现关注点分离,遵循开闭原则,将核心业务与辅助功能解耦,提升系统的可维护性和扩展性。

代理类型选择
  • 静态代理:接口方法较少且固定
  • 动态代理:接口方法多或需要通用处理
  • CGLIB代理:需要代理无接口的类
典型应用场景
  • 安全代理:统一权限校验(如Spring Security)
  • 虚拟代理:延迟加载大资源(如图片预加载)
  • 智能引用:实现缓存机制(如MyBatis Mapper)
实施步骤
  1. 识别需要增强的功能边界(如日志/权限)
  2. 通过接口抽象核心业务能力
  3. 创建代理类委托调用真实对象
  4. 在代理方法中插入横切逻辑
  5. 客户端通过代理访问服务
优势总结
  • 解耦业务逻辑与横切关注点
  • 提高代码复用性和可维护性
  • 支持动态功能扩展
  • 符合开闭原则设计原则
相关推荐
战族狼魂1 小时前
CSGO 皮肤交易平台后端 (Spring Boot) 代码结构与示例
java·spring boot·后端
xyliiiiiL2 小时前
ZGC初步了解
java·jvm·算法
杉之3 小时前
常见前端GET请求以及对应的Spring后端接收接口写法
java·前端·后端·spring·vue
hycccccch3 小时前
Canal+RabbitMQ实现MySQL数据增量同步
java·数据库·后端·rabbitmq
bobz9654 小时前
k8s 怎么提供虚拟机更好
后端
bobz9654 小时前
nova compute 如何创建 ovs 端口
后端
天天向上杰4 小时前
面基JavaEE银行金融业务逻辑层处理金融数据类型BigDecimal
java·bigdecimal
请来次降维打击!!!5 小时前
优选算法系列(5.位运算)
java·前端·c++·算法
用键盘当武器的秋刀鱼5 小时前
springBoot统一响应类型3.5.1版本
java·spring boot·后端
嘤国大力士5 小时前
C++11&QT复习 (七)
java·c++·qt