设计模式-代理模式

写在前面

❝

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. 客户端通过代理访问服务
优势总结
  • 解耦业务逻辑与横切关注点
  • 提高代码复用性和可维护性
  • 支持动态功能扩展
  • 符合开闭原则设计原则
相关推荐
IT_陈寒10 分钟前
Python的列表推导式用不好真的会爆内存你知道吗
前端·人工智能·后端
Wang's Blog13 分钟前
Java 项目实战: 交友项目 - 圈子互动章总结与自检清单
java·bootstrap·交友
xyouyuweizhu1 小时前
字节流与字符流:Java IO 的两条主线该怎么选
java·开发语言·python
代码方舟1 小时前
零信任架构实战:基于天远人企关联构建自动化供应链核心企业关联穿透与利益冲突审查网关
java·人工智能·架构·自动化
摸爬滚打的小李2 小时前
TomCat
后端
liyi_hz20082 小时前
O2OA(翱途) V10.1 即将发布|功能再升级,安全再加固,协同更高效!
java·javascript·windows·开源软件
骑着蜗牛撵大象3272 小时前
AI Agent 工程化开发实战(三):用 StateGraph 给智能体搭一条可回放的状态流水线
java·开发语言·jvm·ai·状态管理·langgraph·stategraph
itmigrate2 小时前
Rust 里的所有权误区:不是不写 clone 就叫高性能
开发语言·后端·rust
码事漫谈2 小时前
Deepseek v5 来了
后端
爱勇宝2 小时前
你可能成不了技术大佬,然后呢?
前端·后端·程序员