设计模式-策略模式、工厂模式应用示例
工厂模式
一个接口+三个实现类
// ===== 产品抽象:入库单 ===== 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接收消息
装饰者模式
动态给对象添加职责(增强功能), 装饰者和被装饰者实现同一个接口, 装饰者持有被装饰者引用,在调用前后做增强。 核心:用"包装"代替"继承",避免类爆炸。
浙公网安备 33010602011771号