快递柜里的代码革命——代理模式

快递柜里的代码革命——代理模式

  • 一、代理模式的三重奏
  • 二、静态代理的困境
  • 三、动态代理的破局
  • 四、模式应用启示
  • 五、模式演进启示

快递柜里的代码革命——代理模式_第1张图片

居民李姐最近发现小区的快递服务焕然一新。原来的露天货架换成了智能快递柜,快递员扫码存件、居民取件码开柜,还能代收生鲜冷藏包裹。更神奇的是,这个柜子能同时处理顺丰、京东、邮政等所有快递公司的包裹,自动发送取件提醒,甚至能识别异常包裹自动报警…

一、代理模式的三重奏

1. 抽象主题(Subject) :快递服务标准接口
2. 真实主题(Real Subject):顺丰、京东快递服务商
3. 代理(Proxy):智能快递柜的智能处理层

/**
 * 抽象主题:快递服务标准接口
 * 定义所有快递公司必须实现的存/取方法
 */
interface DeliveryService {
    void storePackage(String trackingNumber); // 存件操作
    String fetchPackage(String trackingNumber); // 取件操作
}

/**
 * 真实主题:顺丰快递服务实现类
 * 包含核心业务逻辑,但缺乏安全控制和扩展功能
 */
class SFExpress implements DeliveryService {
    @Override
    public void storePackage(String trackingNumber) {
        System.out.println("[顺丰] 包裹入库: " + trackingNumber);
    }

    @Override
    public String fetchPackage(String trackingNumber) {
        return "[顺丰] 包裹内容:电子产品";
    }
}

/**
 * 代理:智能快递柜的智能处理层(顺丰代理)
 */
class SFProxy implements DeliveryService {
    private SFExpress sfExpress;
    
    public SFProxy(DeliveryService service) {
        this.sfExpress = service;
    }
    
    public void store(String code) {
        checkSecurity(code); // 安全校验
        sfExpress.store(code);
        sendNotification(code); // 发送通知
    }
    
    public String pickup(String code) {
        verifyCode(code); // 验证取件码
        return sfExpress.pickup(code);
    }
}

二、静态代理的困境

问题场景
当需要支持多家快递公司时,传统静态代理面临挑战:

// 顺丰代理
class SFProxy extends LockerProxy { /* 重复实现 */ }

// 京东代理 
class JDProxy extends LockerProxy { /* 重复代码 */ }

// 邮政代理
class PostalProxy extends LockerProxy { /* 重复代码 */ }

四大痛点

  1. 类爆炸:每新增一家快递公司需新建代理类
  2. 维护噩梦:接口变更需修改所有代理类
  3. 功能冗余:相同增强逻辑(如安全校验)需重复编写
  4. 灵活性差:无法动态适应业务变化

三、动态代理的破局

动态代理代码实现:

import java.lang.reflect.*;

/**
 * 智能快递柜代理处理器(动态代理核心)
 * 统一处理各家快递公司的增强需求
 */
class SmartLockerHandler implements InvocationHandler {
    private Object target; // 被代理的快递公司实例
    private Map<String, String> verificationCodes = new HashMap<>(); // 取件码缓存

    // 绑定目标对象
    public Object bind(Object target) {
        this.target = target;
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            this);
    }

    // 统一处理方法调用
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String trackingNumber = (String) args[0];
        
        // 存件增强逻辑
        if (method.getName().equals("storePackage")) {
            generateVerificationCode(trackingNumber); // 生成取件码
            notifyUser(trackingNumber); // 发送通知
            checkSecurity(trackingNumber); // 安全扫描
        }
        
        // 取件增强逻辑
        if (method.getName().equals("fetchPackage")) {
            if (!verifyCode(trackingNumber)) {
                throw new SecurityException("取件码验证失败");
            }
        }

        // 执行原始方法
        Object result = method.invoke(target, args);
        
        // 后置处理
        if (method.getName().equals("storePackage")) {
            logStorage(trackingNumber); // 记录存件日志
        }
        return result;
    }

    // 私有增强方法(以下为代理扩展功能)
    private void generateVerificationCode(String trackingNumber) {
        String code = "VC" + trackingNumber.hashCode();
        verificationCodes.put(trackingNumber, code);
        System.out.println("生成取件码: " + code);
    }

    private void notifyUser(String trackingNumber) {
        System.out.println("短信通知: 取件码已发送至用户手机");
    }

    private void checkSecurity(String trackingNumber) {
        System.out.println("安全扫描: X光检测包裹安全性");
    }

    private boolean verifyCode(String trackingNumber) {
        return verificationCodes.containsKey(trackingNumber);
    }

    private void logStorage(String trackingNumber) {
        System.out.println("存储日志: " + trackingNumber + " 存入时间 " + LocalDateTime.now());
    }
}

客户端演示类:

/**
 * 客户端演示类 - 展示动态代理四大优势:
 * 1. 多服务统一处理  2. 功能热插拔  3. 零代码入侵  4. 集中式控制
 */
public class CommunityClient {
    public static void main(String[] args) {
        // 创建代理处理器(快递柜实例)
        SmartLockerHandler smartLocker = new SmartLockerHandler();
        
        // 动态代理不同快递公司(无需创建多个代理类)
        DeliveryService sfProxy = (DeliveryService) smartLocker.bind(new SFExpress());
        DeliveryService jdProxy = (DeliveryService) smartLocker.bind(new JDLogistics());

        System.out.println("======= 顺丰快递流程 =======");
        processDelivery(sfProxy, "SF20230715001");
        
        System.out.println("\n======= 京东物流流程 =======");
        processDelivery(jdProxy, "JD20230715002");
    }

    private static void processDelivery(DeliveryService service, String trackingNumber) {
        // 存件操作(自动增强)
        service.storePackage(trackingNumber);
        
        // 取件操作(自动验证)
        try {
            String content = service.fetchPackage(trackingNumber);
            System.out.println("取件成功: " + content);
        } catch (SecurityException e) {
            System.out.println("取件失败: " + e.getMessage());
        }
    }
}

/* 运行输出:
======= 顺丰快递流程 =======
生成取件码: VCSF20230715001
短信通知: 取件码已发送至用户手机
安全扫描: X光检测包裹安全性
[顺丰] 包裹入库: SF20230715001
存储日志: SF20230715001 存入时间 2023-07-15T09:30:00
取件成功: [顺丰] 包裹内容:电子产品

======= 京东物流流程 =======
生成取件码: VCJD20230715002
短信通知: 取件码已发送至用户手机
安全扫描: X光检测包裹安全性
[京东] 包裹入库: JD20230715002
存储日志: JD20230715002 存入时间 2023-07-15T09:30:05
取件成功: [京东] 包裹内容:生鲜食品
*/

革命性优势

静态代理 动态代理
扩展能力 每公司需新代理类 一套处理器适配所有快递公司
维护成本 修改N个代理类 修改1个处理器即可
执行效率 直接调用(快) 反射调用(毫秒级损耗)
功能迭代 需修改每个代理类 统一增强所有服务
技术复杂度 简单但冗余 复杂但优雅

四、模式应用启示

行业级应用场景

  • 金融交易:支付网关代理实现风控拦截
  • 物联网:设备代理实现协议转换
  • 云服务:API网关代理实现负载均衡
  • 游戏开发:网络请求代理实现延迟补偿

框架集成实例

// Spring AOP事务管理(动态代理实现)
@Transactional 
public void placeOrder() {
    // 自动添加事务边界
}

// MyBatis Mapper代理(接口方法转SQL)
public interface ProductMapper {
    @Select("SELECT * FROM products WHERE sku = #{sku}")
    Product selectBySku(String sku); // 动态生成实现类
}

五、模式演进启示

从静态代理到动态代理的演进,体现了软件设计的核心原则:

  1. 开闭原则:动态代理通过统一处理器实现功能扩展,避免修改已有代码
  2. 单一职责:代理层专注控制逻辑,与业务代码解耦
  3. 高内聚低耦合:动态生成机制使代理类与真实主题无编译期依赖

行业应用:Spring框架的声明式事务管理,通过动态代理在运行时为DAO层方法自动添加事务边界,无需侵入业务代码

通过动态代理技术,开发者能构建出弹性更强、更易维护的系统架构,这是现代框架设计的基石之一。

你可能感兴趣的:(设计模式,算法+数据结构+设计模式,代理模式,设计模式)