设计模式-策略模式、工厂模式应用示例

工厂模式

一个接口+三个实现类

// ===== 产品抽象:入库单 =====
public interface InOrder {
    String getOrderType();   // 单据类型
    void create();           // 创建单据
}

// ===== 具体产品1:采购入库单 =====
public class PurchaseInOrder implements InOrder {
    private String orderNo;
    public PurchaseInOrder(String orderNo) { this.orderNo = orderNo; }
    @Override
    public String getOrderType() { return "采购入库"; }
    @Override
    public void create() {
        System.out.println("创建采购入库单:" + orderNo);
    }
}

// ===== 具体产品2:生产入库单 =====
public class ProductionInOrder implements InOrder {
    private String orderNo;
    public ProductionInOrder(String orderNo) { this.orderNo = orderNo; }
    @Override
    public String getOrderType() { return "生产入库"; }
    @Override
    public void create() {
        System.out.println("创建生产入库单:" + orderNo);
    }
}

// ===== 具体产品3:其他入库单 =====
public class OtherInOrder implements InOrder {
    private String orderNo;
    public OtherInOrder(String orderNo) { this.orderNo = orderNo; }
    @Override
    public String getOrderType() { return "其他入库"; }
    @Override
    public void create() {
        System.out.println("创建其他入库单:" + orderNo);
    }
}

简单工厂

// ===== 简单工厂:一个工厂类,if-else 判断 =====
public class InOrderFactory {

    // 工厂方法:根据类型创建对应单据
    public static InOrder createInOrder(String type, String orderNo) {
        if ("PURCHASE".equals(type)) {
            return new PurchaseInOrder(orderNo);
        } else if ("PRODUCTION".equals(type)) {
            return new ProductionInOrder(orderNo);
        } else if ("OTHER".equals(type)) {
            return new OtherInOrder(orderNo);
        }
        throw new IllegalArgumentException("未知入库类型:" + type);
    }
}

// ===== 使用 =====
InOrder order = InOrderFactory.createInOrder("PURCHASE", "PO20260905");
order.create();   // 创建采购入库单:PO20260905

缺点:加一种入库类型(比如 "退货入库")→ 要改 createInOrder 加一个 else-if → 修改已有的工厂代码(违反开闭原则)。

工厂方法模式(正统 GoF 工厂模式,满足开闭原则)

 
// ===== 工厂抽象:每个产品对应一个工厂 =====
public interface InOrderFactory {
    InOrder createInOrder(String orderNo);
}

// ===== 具体工厂1:采购入库工厂 =====
public class PurchaseInOrderFactory implements InOrderFactory {
    @Override
    public InOrder createInOrder(String orderNo) {
        return new PurchaseInOrder(orderNo);
    }
}

// ===== 具体工厂2:生产入库工厂 =====
public class ProductionInOrderFactory implements InOrderFactory {
    @Override
    public InOrder createInOrder(String orderNo) {
        return new ProductionInOrder(orderNo);
    }
}

// ===== 具体工厂3:其他入库工厂 =====
public class OtherInOrderFactory implements InOrderFactory {
    @Override
    public InOrder createInOrder(String orderNo) {
        return new OtherInOrder(orderNo);
    }
}
// ===== 使用 =====
// 调用方持有工厂接口,具体用哪个工厂由"配置/上层"决定
public class InOrderService {

    private InOrderFactory factory;   // 注入具体工厂

    public InOrderService(InOrderFactory factory) {
        this.factory = factory;       // 构造注入(Spring 里就是 @Autowired)
    }

    public void createInOrder(String orderNo) {
        InOrder order = factory.createInOrder(orderNo);
        order.create();
    }
}

// 入口:选择工厂(这就是"配置",不写死在工厂里)
public class App {
    public static void main(String[] args) {
        // 假设根据来源选择工厂(ERP推送采购 → 采购工厂)
        InOrderFactory factory = new PurchaseInOrderFactory();
        InOrderService service = new InOrderService(factory);
        service.createInOrder("PO20260905");
    }
}

优点:加 "退货入库" → 新建 ReturnInOrder + ReturnInOrderFactory,不改任何已有代码,只在上层选择新工厂 → 满足开闭原则。

 策略模式

把一组"可替换的算法"封装成各自的类, 调用方持有策略接口,运行时可以切换具体策略

 场景:出库分配策略
同一件事:查库存后按什么顺序分配货物? FEFO 先过期先出 → 按到期日期升序 FIFO 先进先出 → 按生产日期升序 指定批次 → 只从指定批次出 → 三种"算法",随时可切换 → 策略模式
1. 策略接口
// ===== 策略抽象:库存分配策略 =====
public interface AllocateStrategy {
    /** 按策略对可用库存排序/筛选,返回"先出谁"的顺序 */
    List<WmsStock> order(List<WmsStock> stocks, String specBatchNo);
}

2. 具体策略(三个策略类)

// ===== 策略1:FEFO 先过期先出(按到期日期升序)=====
public class FefoStrategy implements AllocateStrategy {
    @Override
    public List<WmsStock> order(List<WmsStock> stocks, String specBatchNo) {
        return stocks.stream()
                .filter(s -> s.getExpireDate() != null)
                .sorted(Comparator.comparing(WmsStock::getExpireDate))  // 到期日最近的先出
                .collect(Collectors.toList());
    }
}

// ===== 策略2:FIFO 先进先出(按生产日期升序)=====
public class FifoStrategy implements AllocateStrategy {
    @Override
    public List<WmsStock> order(List<WmsStock> stocks, String specBatchNo) {
        return stocks.stream()
                .sorted(Comparator.comparing(WmsStock::getProduceDate))  // 生产最早的先出
                .collect(Collectors.toList());
    }
}

// ===== 策略3:指定批次(只从指定批次出)=====
public class SpecifyBatchStrategy implements AllocateStrategy {
    @Override
    public List<WmsStock> order(List<WmsStock> stocks, String specBatchNo) {
        return stocks.stream()
                .filter(s -> specBatchNo.equals(s.getBatchNo()))  // 只留指定批次
                .collect(Collectors.toList());
    }
}

3. 上下文(持有策略,可切换)

// ===== 上下文:使用策略的客户 =====
public class OutOrderService {

    private AllocateStrategy strategy;   // 持有策略接口

    // 运行时切换策略(这就是"可替换")
    public void setStrategy(AllocateStrategy strategy) {
        this.strategy = strategy;
    }

    // 分配逻辑:只依赖接口,不关心具体策略
    public void allocate(String goodsId, int needQty, String specBatchNo) {
        List<WmsStock> stocks = stockMapper.selectByGoods(goodsId);
        List<WmsStock> ordered = strategy.order(stocks, specBatchNo);  // 多态调用
    }
}

4. 使用(切换策略)

// ===== 入口:根据商品配置选择策略 =====
OutOrderService service = new OutOrderService();

// 化肥(有保质期)→ FEFO
service.setStrategy(new FefoStrategy());
service.allocate("FERT001", 100, null);

// 橡胶(无保质期,先进先出)→ FIFO
service.setStrategy(new FifoStrategy());
service.allocate("RUBBER01", 50, null);

// 客户指定批次 → 指定批次策略
service.setStrategy(new SpecifyBatchStrategy());
service.allocate("FERT001", 30, "B20260901");

责任链模式

责任链模式:多个处理者组成一条链, 请求沿链传递. 核心:请求发送者不知道谁会处理它,处理者之间解耦。

风控场景,将多个风控规则串成链

// ===== 用 @Order 排序 + List 注入,自动成链 =====
@Component
public class RiskChain {

    @Autowired
    private List<RiskHandler> handlers;   // 按 @Order 值升序注入(黑名单→金额→频次)

    public void execute(OutOrder order) {
        for (RiskHandler handler : handlers) {
            if (!handler.doHandle(order)) {
                break;                    // 任一不过 → 断链
            }
        }
    }
}

// 每个处理者标顺序:
@Component @Order(1)
public class BlacklistHandler extends RiskHandler { ... }

@Component @Order(2)
public class AmountRiskHandler extends RiskHandler { ... }

@Component @Order(3)
public class FrequencyRiskHandler extends RiskHandler { ... }

// 加新风控(如"收货地址风险")→ 只加一个 @Order(4) 类,链自动变长 ✅

 

观察者模式

被观察者给mq的某个topic发消息,多个观察者订阅这个topic接收消息

装饰者模式

动态给对象添加职责(增强功能), 装饰者和被装饰者实现同一个接口, 装饰者持有被装饰者引用,在调用前后做增强。 核心:用"包装"代替"继承",避免类爆炸。

posted @ 2024-06-24 17:22  杨吃羊  阅读(65)  评论(0)    收藏  举报