面试官:责任链模式、工厂模式、观察者模式的实际应用场景?

425 阅读7分钟

记得三年前面试某金融科技公司时,技术总监曾抛出一个经典问题:“订单创建需要经过参数校验、库存检查、价格计算等多个环节,如何设计一个可扩展的流程处理架构?” 这个问题直击设计模式在复杂业务中的应用核心,也让我意识到:真正的代码质量保障,始于对设计模式的深度理解与灵活运用。

一、代码质量保障的基石:设计模式的战略价值

1. 设计模式与代码质量的三维关系

维度设计模式的贡献质量指标提升
可维护性降低耦合度(如工厂模式解耦对象创建)变更成本下降 40%(基于某电商系统数据)
可扩展性支持开闭原则(如观察者模式动态注册监听器)新功能开发周期缩短 30%
可测试性依赖注入(如工厂模式返回接口)单测覆盖率提升 25%

2. 设计模式的选择矩阵

// 设计模式选择决策树(简化版)
public DesignPattern selectPattern(CodeSmell smell) {
    if (smell.isLongConditional()) {
        return new StrategyPattern();
    } else if (smell.isTightCoupling()) {
        return new FactoryPattern();
    } else if (smell.isStateTransition()) {
        return new StatePattern();
    }
    // 默认返回简单重构
    return new ExtractMethod();
}

二、责任链模式:构建灵活的处理流程

1. 原理与结构

(1)核心定义

将请求的发送者和接收者解耦,使多个对象都有机会处理这个请求。请求沿着链传递,直到有一个对象处理它为止。

(2)结构组成

  • Handler:定义处理请求的接口
  • ConcreteHandler:实现处理逻辑,决定是否将请求传递给下一个处理器
  • Client:创建处理链并发送请求

2. 实战场景:订单处理流程(电商系统)

(1)场景分析

订单创建需经过:参数校验→库存检查→价格计算→优惠应用→日志记录等环节,每个环节都可能终止流程。

(2)核心代码实现

// 订单处理器接口
public interface OrderHandler {
    boolean process(OrderContext context);
    void setNextHandler(OrderHandler nextHandler);
}

// 参数校验处理器
public class ParamValidationHandler implements OrderHandler {
    private OrderHandler nextHandler;
    
    @Override
    public boolean process(OrderContext context) {
        // 校验参数逻辑
        if (context.getUserId() == null || context.getProductId() == null) {
            context.setError("参数缺失");
            return false;
        }
        // 传递给下一个处理器
        return nextHandler != null ? nextHandler.process(context) : true;
    }
    
    @Override
    public void setNextHandler(OrderHandler nextHandler) {
        this.nextHandler = nextHandler;
    }
}

// 库存检查处理器
public class InventoryCheckHandler implements OrderHandler {
    private final InventoryService inventoryService;
    
    public InventoryCheckHandler(InventoryService inventoryService) {
        this.inventoryService = inventoryService;
    }
    
    @Override
    public boolean process(OrderContext context) {
        // 检查库存逻辑
        if (!inventoryService.hasStock(context.getProductId(), context.getQuantity())) {
            context.setError("库存不足");
            return false;
        }
        return nextHandler != null ? nextHandler.process(context) : true;
    }
    
    // 省略setNextHandler实现
}

// 客户端:构建处理链并执行
public class OrderService {
    public OrderResult createOrder(OrderDTO orderDTO) {
        // 构建处理链
        OrderHandler paramValidator = new ParamValidationHandler();
        OrderHandler inventoryChecker = new InventoryCheckHandler(inventoryService);
        OrderHandler priceCalculator = new PriceCalculationHandler();
        
        // 设置链顺序
        paramValidator.setNextHandler(inventoryChecker);
        inventoryChecker.setNextHandler(priceCalculator);
        
        // 创建上下文并处理
        OrderContext context = new OrderContext(orderDTO);
        boolean success = paramValidator.process(context);
        
        return success ? 
            OrderResult.success(context.getOrder()) : 
            OrderResult.fail(context.getError());
    }
}

(3)工程优势

  • 流程可视化:通过 Handler 实现类名称直接反映处理步骤
  • 易于扩展:新增校验逻辑只需实现 Handler 并插入链中
  • 单元测试友好:可单独测试每个 Handler 的逻辑正确性

三、工厂模式:解耦对象创建与使用

1. 原理与结构

(1)核心定义

定义一个创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。

(2)结构组成

  • Product:定义产品的接口
  • ConcreteProduct:实现产品接口的具体类
  • Creator:声明工厂方法,返回产品对象
  • ConcreteCreator:实现工厂方法,创建具体产品

2. 实战场景:支付渠道选择(金融系统)

(1)场景分析

系统支持支付宝、微信、银行卡等多种支付方式,需根据用户选择动态创建支付处理器。

(2)核心代码实现

// 支付处理器接口
public interface PaymentProcessor {
    PaymentResult process(PaymentRequest request);
}

// 支付宝处理器
public class AlipayProcessor implements PaymentProcessor {
    private final AlipayClient alipayClient;
    
    @Override
    public PaymentResult process(PaymentRequest request) {
        // 支付宝支付逻辑
        AlipayTradeRequest alipayRequest = convertToAlipayRequest(request);
        AlipayTradeResponse response = alipayClient.execute(alipayRequest);
        return mapToPaymentResult(response);
    }
}

// 微信支付处理器
public class WechatPayProcessor implements PaymentProcessor {
    private final WechatPayClient wechatPayClient;
    
    @Override
    public PaymentResult process(PaymentRequest request) {
        // 微信支付逻辑
        WechatPayRequest wechatRequest = convertToWechatRequest(request);
        WechatPayResponse response = wechatPayClient.execute(wechatRequest);
        return mapToPaymentResult(response);
    }
}

// 支付工厂
public class PaymentProcessorFactory {
    // 工厂方法:根据支付类型创建处理器
    public PaymentProcessor createProcessor(PaymentType type) {
        switch (type) {
            case ALIPAY:
                return new AlipayProcessor(alipayClient);
            case WECHAT_PAY:
                return new WechatPayProcessor(wechatPayClient);
            case BANK_CARD:
                return new BankCardProcessor(bankCardClient);
            default:
                throw new IllegalArgumentException("不支持的支付类型: " + type);
        }
    }
}

// 客户端使用
public class PaymentService {
    private final PaymentProcessorFactory factory;
    
    public PaymentResult executePayment(PaymentDTO paymentDTO) {
        // 通过工厂创建处理器
        PaymentProcessor processor = factory.createProcessor(paymentDTO.getType());
        // 执行支付
        return processor.process(convertToRequest(paymentDTO));
    }
}

(3)工程优势

  • 依赖倒置:Service 依赖接口而非具体实现类
  • 开闭原则:新增支付方式只需添加新的 Processor 实现和工厂分支
  • 测试隔离:可通过 Mock 工厂返回测试对象

四、观察者模式:实现松耦合的事件通知

1. 原理与结构

(1)核心定义

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。

(2)结构组成

  • Subject:主题接口,定义添加、删除和通知观察者的方法
  • ConcreteSubject:具体主题,维护观察者列表,状态变化时通知观察者
  • Observer:观察者接口,定义响应通知的方法
  • ConcreteObserver:具体观察者,实现响应逻辑

2. 实战场景:订单状态变更通知(电商系统)

(1)场景分析

订单状态变更(如支付成功、发货、签收)需通知多个系统:库存系统、物流系统、消息推送系统等。

(2)核心代码实现

// 观察者接口
public interface OrderStatusObserver {
    void update(Order order);
}

// 主题接口
public interface OrderStatusSubject {
    void registerObserver(OrderStatusObserver observer);
    void removeObserver(OrderStatusObserver observer);
    void notifyObservers();
}

// 订单实现主题接口
public class Order implements OrderStatusSubject {
    private List<OrderStatusObserver> observers = new ArrayList<>();
    private OrderStatus status;
    
    @Override
    public void registerObserver(OrderStatusObserver observer) {
        observers.add(observer);
    }
    
    @Override
    public void removeObserver(OrderStatusObserver observer) {
        observers.remove(observer);
    }
    
    @Override
    public void notifyObservers() {
        for (OrderStatusObserver observer : observers) {
            observer.update(this);
        }
    }
    
    // 状态变更时通知观察者
    public void setStatus(OrderStatus status) {
        this.status = status;
        notifyObservers();
    }
}

// 库存系统观察者
public class InventoryObserver implements OrderStatusObserver {
    private final InventoryService inventoryService;
    
    @Override
    public void update(Order order) {
        if (order.getStatus() == OrderStatus.PAID) {
            // 支付成功,扣减库存
            inventoryService.reduceStock(order.getProductId(), order.getQuantity());
        }
    }
}

// 物流系统观察者
public class LogisticsObserver implements OrderStatusObserver {
    private final LogisticsService logisticsService;
    
    @Override
    public void update(Order order) {
        if (order.getStatus() == OrderStatus.SHIPPED) {
            // 发货,创建物流单
            logisticsService.createWaybill(order.getId());
        }
    }
}

// 客户端使用
public class OrderService {
    public void payOrder(Long orderId) {
        // 获取订单
        Order order = orderRepository.findById(orderId);
        
        // 注册观察者
        order.registerObserver(new InventoryObserver(inventoryService));
        order.registerObserver(new MessageObserver(messageService));
        
        // 更新状态,自动触发通知
        order.setStatus(OrderStatus.PAID);
    }
}

(3)工程优势

  • 松耦合:订单服务不直接依赖库存、物流等系统
  • 可扩展性:新增通知系统只需实现 Observer 接口并注册
  • 异步处理:可结合线程池实现异步通知,提升性能

五、设计模式的组合应用:解决复杂场景

1. 工厂 + 策略:动态选择算法(金融风控)

// 风险评估策略接口
public interface RiskStrategy {
    RiskLevel assess(Transaction transaction);
}

// 高风险策略
public class HighRiskStrategy implements RiskStrategy {
    @Override
    public RiskLevel assess(Transaction transaction) {
        // 高风险评估逻辑
    }
}

// 策略工厂
public class RiskStrategyFactory {
    public RiskStrategy createStrategy(Customer customer) {
        if (customer.getAccountAge() < 30) {
            return new HighRiskStrategy();
        } else if (customer.getTransactionCount() > 100) {
            return new LowRiskStrategy();
        } else {
            return new MediumRiskStrategy();
        }
    }
}

2. 责任链 + 观察者:复杂流程监控(医疗系统)

// 患者检查流程处理器
public abstract class PatientCheckHandler implements OrderStatusObserver {
    protected PatientCheckHandler nextHandler;
    
    public abstract boolean process(Patient patient);
    
    public void setNextHandler(PatientCheckHandler nextHandler) {
        this.nextHandler = nextHandler;
    }
    
    // 实现观察者接口,响应检查状态变更
    @Override
    public void update(Patient patient) {
        if (canHandle(patient.getStatus())) {
            boolean success = process(patient);
            if (success && nextHandler != null) {
                nextHandler.update(patient);
            }
        }
    }
    
    protected abstract boolean canHandle(PatientStatus status);
}

六、八年实战经验:设计模式的正确打开方式

1. 选型决策树

WX20250613-092956@2x.png

2. 实施原则

  • 最小知识原则:每个模块只了解与其直接交互的模块
  • 渐进式引入:先通过 Extract Method 重构,再引入模式
  • 工具辅助:使用 UML 工具(如 PlantUML)设计模式结构

建议开发者从以下路径实践:

  1. 识别代码异味:如长方法、重复逻辑、紧耦合等

  2. 匹配对应模式:如条件判断多→策略模式,对象创建复杂→工厂模式

  3. 小步重构:先提取接口,再实现模式,最后替换调用点

记住:优秀的代码不是一次性写成的,而是通过持续重构和模式应用「进化」而来。当我们在代码中应用责任链处理流程、用工厂解耦创建、用观察者实现通知时,不仅是在提升代码质量,更是在培养对系统架构的洞察力。这才是八年设计模式实践带给我们最宝贵的财富 —— 让代码在变化中保持优雅,在演进中持续发光。