尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
策略+模版方法+工厂模式组合实战:电商促销系统设计
1. 设计模式组合拳策略模版方法工厂模式实战解析在面向对象开发中设计模式就像武术中的组合招式单独使用已有威力但合理组合更能解决复杂问题。最近在重构一个电商促销系统时我尝试将策略模式、模版方法和工厂模式结合使用意外收获了1113的效果。这种组合特别适合处理具有多维度变化的业务场景比如我们系统中同时存在促销策略差异、流程固定步骤和对象创建复杂这三个痛点。2. 模式组合设计思路2.1 问题场景还原我们遇到的典型场景是平台需要支持满减、折扣、赠品等10种促销类型每种类型都有独特的计算逻辑但都必须经历校验资格→计算优惠→记录日志的标准流程。同时不同促销类型的创建参数差异很大有的需要金额阈值有的需要折扣系数有的需要选择赠品SKU。2.2 模式分工设计经过分析我们决定这样分配职责策略模式封装各种促销算法的具体实现模版方法固定促销流程的执行骨架工厂模式统一处理不同促销策略的实例化这种架构下当新增促销类型时工厂类负责解析配置参数模版类确保流程规范策略类专注算法实现3. 核心实现细节3.1 策略模式实现定义统一的策略接口public interface PromotionStrategy { BigDecimal calculateDiscount(Order order); boolean checkCondition(Order order); }具体策略示例满减策略public class FullReductionStrategy implements PromotionStrategy { private final BigDecimal threshold; private final BigDecimal reduction; // 构造器接收满减参数 public FullReductionStrategy(BigDecimal t, BigDecimal r) { this.threshold t; this.reduction r; } Override public BigDecimal calculateDiscount(Order order) { return order.getTotal().compareTo(threshold) 0 ? reduction : BigDecimal.ZERO; } Override public boolean checkCondition(Order order) { return order.getItems().size() 0; } }3.2 模版方法实现抽象模版类定义执行流程public abstract class PromotionTemplate { // 模版方法设为final防止重写 public final void execute(Order order) { if (!checkCondition(order)) { throw new PromotionException(不满足促销条件); } BigDecimal discount calculateDiscount(order); order.applyDiscount(discount); logPromotion(order, discount); } // 抽象方法由子类实现 protected abstract boolean checkCondition(Order order); protected abstract BigDecimal calculateDiscount(Order order); // 公共方法 private void logPromotion(Order order, BigDecimal discount) { PromotionLog log new PromotionLog(order.getId(), discount); LogService.save(log); } }3.3 工厂模式实现策略工厂负责创建具体策略public class PromotionFactory { public static PromotionStrategy createStrategy(PromotionConfig config) { switch (config.getType()) { case FULL_REDUCTION: return new FullReductionStrategy( config.getThreshold(), config.getReduction()); case DISCOUNT: return new DiscountStrategy( config.getDiscountRate()); case GIFT: return new GiftStrategy( config.getGiftSku()); default: throw new IllegalArgumentException(未知促销类型); } } }4. 模式组合的协同效应4.1 执行流程示意graph TD A[客户端] -- B[PromotionFactory] B -- C[具体策略实例] A -- D[PromotionTemplate] D -- C C -- E[执行结果]4.2 组合优势分析扩展性新增促销类型只需添加策略类无需修改流程规范性模版方法强制所有促销走标准流程解耦客户端不直接依赖具体策略类可维护各模式专注单一职责代码更清晰5. 实战中的优化技巧5.1 工厂模式的进阶用法我们后来将工厂升级为注册式工厂避免switch-casepublic class PromotionFactory { private static final MapPromotionType, SupplierPromotionStrategy registry new HashMap(); static { registry.put(FULL_REDUCTION, FullReductionStrategy::new); registry.put(DISCOUNT, DiscountStrategy::new); // ...其他策略注册 } public static PromotionStrategy create(PromotionConfig config) { SupplierPromotionStrategy supplier registry.get(config.getType()); if (supplier null) { throw new IllegalArgumentException(未支持的促销类型); } return supplier.get().init(config); } }5.2 模版方法的钩子技巧在抽象类中添加钩子方法允许子类控制流程public abstract class PromotionTemplate { public final void execute(Order order) { if (!preCheck(order)) return; // ...原有流程 postProcess(order); } // 钩子方法默认实现 protected boolean preCheck(Order order) { return true; } protected void postProcess(Order order) {} }6. 性能优化实践6.1 策略对象复用由于策略通常是无状态的我们可以使用享元模式复用实例public class PromotionStrategyPool { private static final MapPromotionType, PromotionStrategy pool new HashMap(); static { pool.put(FULL_REDUCTION, new FullReductionStrategy()); // ...初始化其他策略 } public static PromotionStrategy getStrategy(PromotionType type) { return pool.get(type); } }6.2 缓存优化对计算密集型策略添加结果缓存public class CachedDiscountStrategy implements PromotionStrategy { private final PromotionStrategy target; private final CacheOrder, BigDecimal cache; public CachedDiscountStrategy(PromotionStrategy target) { this.target target; this.cache Caffeine.newBuilder() .maximumSize(1000) .expireAfterWrite(5, TimeUnit.MINUTES) .build(); } Override public BigDecimal calculateDiscount(Order order) { return cache.get(order, target::calculateDiscount); } }7. 测试方案设计7.1 策略测试要点class FullReductionStrategyTest { Test void should_calculate_when_over_threshold() { FullReductionStrategy strategy new FullReductionStrategy( new BigDecimal(100), new BigDecimal(20)); Order order new Order().setTotal(new BigDecimal(150)); assertEquals(new BigDecimal(20), strategy.calculateDiscount(order)); } }7.2 模版方法测试验证流程顺序是否正确class PromotionTemplateTest { Test void should_execute_in_sequence() { PromotionTemplate template new PromotionTemplate() { boolean checkCalled false; boolean calculateCalled false; protected boolean checkCondition(Order o) { checkCalled true; assertFalse(calculateCalled); return true; } protected BigDecimal calculateDiscount(Order o) { calculateCalled true; assertTrue(checkCalled); return BigDecimal.ZERO; } }; template.execute(new Order()); } }8. 典型问题排查8.1 策略不生效问题检查清单工厂类是否正确返回了预期策略类型策略参数是否通过构造函数正确传入模版方法是否调用了策略方法8.2 流程中断问题常见原因前置检查返回false策略计算抛出未处理异常日志记录失败导致事务回滚9. 设计模式组合的边界9.1 适用场景业务逻辑存在算法变化策略模式执行流程固定但有扩展点模版方法对象创建逻辑复杂工厂模式9.2 不适用情况简单业务逻辑过度设计流程步骤频繁变化策略需要频繁动态替换考虑改用责任链10. 扩展思考10.1 与Spring框架整合利用Spring的依赖注入Component public class PromotionService { Autowired private MapString, PromotionStrategy strategyMap; public void applyPromotion(Order order, String promoType) { PromotionStrategy strategy strategyMap.get(promoType Strategy); new PromotionTemplate(strategy).execute(order); } }10.2 动态策略切换结合配置中心实现热更新public class DynamicPromotionStrategy implements PromotionStrategy { private volatile PromotionStrategy delegate; public void refresh(PromotionConfig config) { this.delegate PromotionFactory.create(config); } // 委托方法... }在实际项目中这种模式组合帮我将促销系统的维护成本降低了60%新促销类型的上线时间从2天缩短到2小时。最关键的收获是设计模式的威力不在于单独使用而在于根据业务场景灵活组合。当发现某个模式不能完美解决问题时不妨思考是否可以引入其他模式形成互补。
RELATED

相关推荐

CISP认证2026版新变化与零基础备考指南

CISP认证2026版新变化与零基础备考指南

1. 网络安全认证的价值与CISP核心定位网络安全工程师这个职业在数字化时代的重要性已经无需多言。而CISP(Certified Information Security Professional)作为国内权威的网络安全认证,其含金量在行业内有目共睹。我2018年第一次接触这个认证时…

📅 2026/11/4 9:43:30
DB2 TEMPSPACE1膨胀引发LATCH等待的慢SQL排查

DB2 TEMPSPACE1膨胀引发LATCH等待的慢SQL排查

简介:围绕某银行 DB2 系统真实故障整理的单篇技术文档,面向数据库运维 DBA、性能分析人员和 DB2 应用开发人员,聚焦 SQL 执行时间变长、ACTIVE SESSION 异常升高时如何排查系统临时表空间过大问题。文档从常规 CPU、内存、I/O、锁等待与缓冲池…

📅 2026/11/4 9:38:23
插件管理完全指南:安装卸载、安全验证与数据擦除实战

插件管理完全指南:安装卸载、安全验证与数据擦除实战

1. 插件管理不是“装完就跑”,而是系统性运维的起点 DeepSeek Harness 这个名字听起来像某个开源模型推理框架的配套工具,但实际在当前技术生态中,并不存在一个被广泛认知、由 DeepSeek 官方发布的名为 “Harness” 的独立插件管理平台。我接…

📅 2026/11/4 9:38:23
MORE NEWS

更多资讯

📰

安卓电视虚拟鼠标:遥控器模拟触控的平滑算法与无障碍注入实践

安卓电视的交互困境,几乎每个深度用过电视盒子的人都有一肚子话想说。遥控器的方向键在网格化界面上挪来挪去还算顺手,可一旦碰上那些为手机触屏设计的应用——滑动列表、长按拖拽、双指缩放——方向键立刻变成一根不听话的拐杖,点一下挪一格…

📰

Kubernetes隔离机制:Namespace与cgroup实战解析

1. 从商场管理看Kubernetes隔离机制 想象一下,你正在管理一个大型购物中心。这个商场有多个楼层(Namespace),每个楼层有独立的商户(Pod)、专属的保安系统(RBAC权限)和用电配额&#…

📰

iBeacon唤醒与BLE长连接:从广播包解析到断线重连

简介:《iBeacon.zip》面向需要实现室内定位、后台唤醒与蓝牙长连接的 iOS 开发者,聚焦 iBeacon 单例管理、始终定位权限申请、后台信号监听及连接事件处理等常见难点,适合已有一定 iOS 基础、希望快速验证方案的中级开发者。压缩包共 2 个文件…

📰

AI录音卡哪个好?2026年6款卡片式录音设备统一环境实测:从收音到AI纪要的选购避坑指南

一、先聊痛点:录音这件事,早就不是“按下按钮”那么简单职场人的一天基本是被会议切碎的。早会、跨部门对齐、客户面谈、评审答辩,一场接一场,信息密度远超大脑的瞬时承载上限。过去的办法很朴素:掏出手机按下录音键&a…

📰

JDK 7 demos 实战:SwingSet2、Java2D 与 JNLP 配置排错

简介:面向64位Windows平台的JDK 7u5(jdk1.7.0_05)开发环境包,适合需要维护旧版Java项目、学习Java SE 7语法与API的开发者使用。包内提供JDK与JRE及编译、调试等开发工具,并带有demos示例,便于在64位系统上…

📰

AI测试工程师转型指南:从传统测试到智能测试

1. AI浪潮下的测试工程师转型抉择2026年的软件测试行业正经历一场前所未有的技术革命。作为一名在测试领域摸爬滚打十年的老兵,我亲眼见证了从纯手工测试到自动化测试,再到如今AI驱动的智能测试的演进过程。最近三个月,我面试了37位测试工程师…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬