设计模式-代理模式

写在前面

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. 客户端通过代理访问服务
优势总结
  • 解耦业务逻辑与横切关注点
  • 提高代码复用性和可维护性
  • 支持动态功能扩展
  • 符合开闭原则设计原则
相关推荐
程序员敲代码吗3 分钟前
如何通过命令行启动COMSOL的参数化、批处理和集群扫描
java·c#·bash
MX_93597 分钟前
Spring的bean工厂后处理器和Bean后处理器
java·后端·spring
市场部需要一个软件开发岗位24 分钟前
JAVA开发常见安全问题:纵向越权
java·数据库·安全
历程里程碑37 分钟前
普通数组----合并区间
java·数据结构·python·算法·leetcode·职场和发展·tornado
程序员泠零澪回家种桔子1 小时前
Spring AI框架全方位详解
java·人工智能·后端·spring·ai·架构
CodeCaptain1 小时前
nacos-2.3.2-OEM与nacos3.1.x的差异分析
java·经验分享·nacos·springcloud
源代码•宸2 小时前
大厂技术岗面试之谈薪资
经验分享·后端·面试·职场和发展·golang·大厂·职级水平的薪资
Anastasiozzzz2 小时前
Java Lambda 揭秘:从匿名内部类到底层原理的深度解析
java·开发语言
骇客野人2 小时前
通过脚本推送Docker镜像
java·docker·容器
铁蛋AI编程实战2 小时前
通义千问 3.5 Turbo GGUF 量化版本地部署教程:4G 显存即可运行,数据永不泄露
java·人工智能·python