设计模式-代理模式

写在前面

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. 客户端通过代理访问服务
优势总结
  • 解耦业务逻辑与横切关注点
  • 提高代码复用性和可维护性
  • 支持动态功能扩展
  • 符合开闭原则设计原则
相关推荐
Java技术小馆3 分钟前
GitDiagram如何让你的GitHub项目可视化
java·后端·面试
Codebee20 分钟前
“自举开发“范式:OneCode如何用低代码重构自身工具链
java·人工智能·架构
星星电灯猴27 分钟前
iOS 性能调试全流程:从 Demo 到产品化的小团队实战经验
后端
程序无bug36 分钟前
手写Spring框架
java·后端
程序无bug37 分钟前
Spring 面向切面编程AOP 详细讲解
java·前端
JohnYan38 分钟前
模板+数据的文档生成技术方案设计和实现
javascript·后端·架构
全干engineer1 小时前
Spring Boot 实现主表+明细表 Excel 导出(EasyPOI 实战)
java·spring boot·后端·excel·easypoi·excel导出
Da_秀1 小时前
软件工程中耦合度
开发语言·后端·架构·软件工程
Fireworkitte1 小时前
Java 中导出包含多个 Sheet 的 Excel 文件
java·开发语言·excel
GodKeyNet1 小时前
设计模式-责任链模式
java·设计模式·责任链模式