¥
立即购买

Java设计模式实例生成器

13 浏览
1 试用
0 购买
Dec 6, 2025更新

本提示词专为Java开发者设计,能够根据指定的设计模式名称生成对应的Java代码实现示例。通过详细的代码注释、结构分析和应用场景说明,帮助开发者深入理解各种设计模式的实现原理和实际应用。输出内容包括完整的类结构定义、方法实现、设计模式核心要素解析以及典型使用场景介绍,确保代码符合Java开发规范和最佳实践。

设计模式概述

  • 模式类型:创建型
  • 模式定义:抽象工厂模式用于创建一组相关或相互依赖的对象(产品族),而无需指定它们的具体类。通过定义抽象工厂接口,将产品族的创建延迟到具体工厂中,从而保证同一产品族内部的一致性与可替换性。
  • 适用场景:
    • 需要为不同平台(桌面、移动端)生成一整套风格统一、行为一致的 UI 控件(按钮、输入框等)
    • 需要支持更换皮肤(主题)而不影响业务逻辑
    • 需要保证同一产品族内的组件彼此兼容并保持一致的交互约束
    • 需要在不修改客户端代码的情况下,平滑切换平台或主题

核心角色

角色 职责说明
AbstractFactory(UIFactory) 定义创建一组相关产品(按钮、输入框)的抽象接口,并允许设置皮肤(Skin)
ConcreteFactory(DesktopUIFactory、MobileUIFactory) 具体工厂,按平台生成成套组件,且与当前皮肤组合输出外观
AbstractProduct(Button、TextField) 定义产品族中各个抽象产品的接口
ConcreteProduct(DesktopButton、MobileButton、DesktopTextField、MobileTextField) 平台相关的具体产品,实现渲染与交互逻辑,并受皮肤影响
Skin(Skin、LightSkin、DarkSkin) 皮肤/主题策略,提供颜色等视觉参数,便于工厂产品组合输出统一风格
Client(AbstractFactoryDemo) 客户端,依赖抽象工厂与抽象产品,通过切换工厂/皮肤达到平台与主题的替换

Java代码实现

/**
 * 抽象工厂模式示例
 * 需求:桌面与移动端需统一主题与交互,抽象出按钮、输入框等控件族,按平台生成成套组件,支持更换皮肤与扩展。
 *
 * 说明:
 * - UIFactory 为抽象工厂,负责创建同一产品族(Button、TextField)
 * - DesktopUIFactory / MobileUIFactory 为具体工厂(按平台)
 * - Button / TextField 为抽象产品
 * - DesktopButton / MobileButton / DesktopTextField / MobileTextField 为具体产品
 * - Skin(LightSkin / DarkSkin)为皮肤策略,可与任何平台工厂组合
 *
 * 编译与运行:
 * javac AbstractFactoryDemo.java
 * java AbstractFactoryDemo
 */

// ========== 抽象产品 ==========

/**
 * 抽象产品:按钮
 */
interface Button {
    /**
     * 渲染按钮(根据平台与皮肤组合输出)
     */
    void render();

    /**
     * 按钮点击事件
     */
    void click();
}

/**
 * 抽象产品:输入框
 */
interface TextField {
    /**
     * 渲染输入框(根据平台与皮肤组合输出)
     */
    void render();

    /**
     * 设置文本内容
     */
    void setText(String text);

    /**
     * 获取文本内容
     */
    String getText();
}

// ========== 皮肤(主题)策略 ==========

/**
 * 皮肤(主题)接口:定义组件渲染所需的视觉参数
 */
interface Skin {
    String getName();
    String getBackgroundColor();
    String getTextColor();
    String getAccentColor();
}

/**
 * 浅色皮肤
 */
class LightSkin implements Skin {
    @Override
    public String getName() {
        return "Light";
    }

    @Override
    public String getBackgroundColor() {
        return "#FFFFFF";
    }

    @Override
    public String getTextColor() {
        return "#222222";
    }

    @Override
    public String getAccentColor() {
        return "#1E88E5"; // 蓝色
    }
}

/**
 * 深色皮肤
 */
class DarkSkin implements Skin {
    @Override
    public String getName() {
        return "Dark";
    }

    @Override
    public String getBackgroundColor() {
        return "#121212";
    }

    @Override
    public String getTextColor() {
        return "#E0E0E0";
    }

    @Override
    public String getAccentColor() {
        return "#BB86FC"; // 紫色
    }
}

// ========== 抽象工厂 ==========

/**
 * 抽象工厂:创建同一产品族(按钮、输入框)
 * 允许设置 Skin 以统一平台下的视觉风格
 */
interface UIFactory {
    Button createButton();
    TextField createTextField();

    void setSkin(Skin skin);
    Skin getSkin();
}

// ========== 具体工厂(按平台) ==========

/**
 * 桌面端工厂:生成桌面端风格组件
 */
class DesktopUIFactory implements UIFactory {
    private Skin skin;

    public DesktopUIFactory(Skin skin) {
        if (skin == null) {
            throw new IllegalArgumentException("Skin must not be null.");
        }
        this.skin = skin;
    }

    @Override
    public Button createButton() {
        return new DesktopButton(skin);
    }

    @Override
    public TextField createTextField() {
        return new DesktopTextField(skin);
    }

    @Override
    public void setSkin(Skin skin) {
        if (skin == null) {
            throw new IllegalArgumentException("Skin must not be null.");
        }
        this.skin = skin;
    }

    @Override
    public Skin getSkin() {
        return this.skin;
    }
}

/**
 * 移动端工厂:生成移动端风格组件
 */
class MobileUIFactory implements UIFactory {
    private Skin skin;

    public MobileUIFactory(Skin skin) {
        if (skin == null) {
            throw new IllegalArgumentException("Skin must not be null.");
        }
        this.skin = skin;
    }

    @Override
    public Button createButton() {
        return new MobileButton(skin);
    }

    @Override
    public TextField createTextField() {
        return new MobileTextField(skin);
    }

    @Override
       public void setSkin(Skin skin) {
        if (skin == null) {
            throw new IllegalArgumentException("Skin must not be null.");
        }
        this.skin = skin;
    }

    @Override
    public Skin getSkin() {
        return this.skin;
    }
}

// ========== 具体产品(平台 + 皮肤组合输出) ==========

/**
 * 桌面端按钮
 */
class DesktopButton implements Button {
    private final Skin skin;

    public DesktopButton(Skin skin) {
        this.skin = skin;
    }

    @Override
    public void render() {
        System.out.println("[Render] Desktop Button");
        System.out.println(" - Skin: " + skin.getName());
        System.out.println(" - Background: " + skin.getBackgroundColor());
        System.out.println(" - Text: " + skin.getTextColor());
        System.out.println(" - Accent: " + skin.getAccentColor());
        System.out.println(" - Style: Flat + Shadow (Desktop)");
    }

    @Override
    public void click() {
        System.out.println("[Action] Desktop Button clicked.");
    }
}

/**
 * 移动端按钮
 */
class MobileButton implements Button {
    private final Skin skin;

    public MobileButton(Skin skin) {
        this.skin = skin;
    }

    @Override
    public void render() {
        System.out.println("[Render] Mobile Button");
        System.out.println(" - Skin: " + skin.getName());
        System.out.println(" - Background: " + skin.getBackgroundColor());
        System.out.println(" - Text: " + skin.getTextColor());
        System.out.println(" - Accent: " + skin.getAccentColor());
        System.out.println(" - Style: Rounded + Ripple (Mobile)");
    }

    @Override
    public void click() {
        System.out.println("[Action] Mobile Button tapped.");
    }
}

/**
 * 桌面端输入框
 */
class DesktopTextField implements TextField {
    private final Skin skin;
    private String text = "";

    public DesktopTextField(Skin skin) {
        this.skin = skin;
    }

    @Override
    public void render() {
        System.out.println("[Render] Desktop TextField");
        System.out.println(" - Skin: " + skin.getName());
        System.out.println(" - Background: " + skin.getBackgroundColor());
        System.out.println(" - Text: " + skin.getTextColor());
        System.out.println(" - Accent: " + skin.getAccentColor());
        System.out.println(" - Style: Outline + Caret (Desktop)");
        System.out.println(" - Current Value: \"" + text + "\"");
    }

    @Override
    public void setText(String text) {
        this.text = text != null ? text : "";
        System.out.println("[Action] Desktop TextField setText -> \"" + this.text + "\"");
    }

    @Override
    public String getText() {
        return this.text;
    }
}

/**
 * 移动端输入框
 */
class MobileTextField implements TextField {
    private final Skin skin;
    private String text = "";

    public MobileTextField(Skin skin) {
        this.skin = skin;
    }

    @Override
    public void render() {
        System.out.println("[Render] Mobile TextField");
        System.out.println(" - Skin: " + skin.getName());
        System.out.println(" - Background: " + skin.getBackgroundColor());
        System.out.println(" - Text: " + skin.getTextColor());
        System.out.println(" - Accent: " + skin.getAccentColor());
        System.out.println(" - Style: Underline + Soft Keyboard Hint (Mobile)");
        System.out.println(" - Current Value: \"" + text + "\"");
    }

    @Override
    public void setText(String text) {
        this.text = text != null ? text : "";
        System.out.println("[Action] Mobile TextField setText -> \"" + this.text + "\"");
    }

    @Override
    public String getText() {
        return this.text;
    }
}

// ========== 客户端演示 ==========

/**
 * 客户端:演示如何通过抽象工厂切换平台与皮肤
 */
public class AbstractFactoryDemo {
    public static void main(String[] args) {
        // 1) 选择皮肤(主题)
        Skin light = new LightSkin();
        Skin dark = new DarkSkin();

        // 2) 选择平台(桌面)+ 皮肤(浅色)
        UIFactory desktopFactory = new DesktopUIFactory(light);
        Button desktopButton = desktopFactory.createButton();
        TextField desktopTextField = desktopFactory.createTextField();

        System.out.println("=== Desktop + Light Skin ===");
        desktopButton.render();
        desktopButton.click();
        desktopTextField.setText("Hello Desktop");
        desktopTextField.render();

        // 3) 切换皮肤到深色(不影响已创建的组件,只影响新创建的组件)
        desktopFactory.setSkin(dark);
        Button desktopButtonDark = desktopFactory.createButton();
        TextField desktopTextFieldDark = desktopFactory.createTextField();

        System.out.println("\n=== Desktop + Dark Skin ===");
        desktopButtonDark.render();
        desktopTextFieldDark.setText("Dark Mode");
        desktopTextFieldDark.render();

        // 4) 切换平台为移动端,沿用当前皮肤(深色)
        UIFactory mobileFactory = new MobileUIFactory(desktopFactory.getSkin());
        Button mobileButton = mobileFactory.createButton();
        TextField mobileTextField = mobileFactory.createTextField();

        System.out.println("\n=== Mobile + Dark Skin ===");
        mobileButton.render();
        mobileButton.click();
        mobileTextField.setText("Hello Mobile");
        mobileTextField.render();

        // 5) 再次切回浅色皮肤,移动端组件创建新的浅色风格
        mobileFactory.setSkin(light);
        Button mobileButtonLight = mobileFactory.createButton();
        System.out.println("\n=== Mobile + Light Skin ===");
        mobileButtonLight.render();

        System.out.println("\nDone.");
    }
}

实现要点

  • 抽象工厂与产品族:
    • UIFactory 定义了创建同一产品族(Button、TextField)的工厂接口,保证了组件族内风格与交互一致。
    • DesktopUIFactory、MobileUIFactory 分别产出桌面端与移动端组件族。
  • 皮肤作为可组合策略:
    • Skin 提供渲染所需的视觉参数,LightSkin、DarkSkin 为实现。
    • 工厂持有 Skin,可切换皮肤以影响新创建的组件外观,避免平台×皮肤产生类爆炸(无需 DesktopLightFactory、DesktopDarkFactory 等组合类)。
  • 解耦与扩展性:
    • 客户端仅依赖抽象接口(UIFactory、Button、TextField、Skin),可在运行时切换平台与皮肤。
    • 新增平台:增加一个新的具体工厂与成套具体产品类即可(不影响既有客户端代码)。
    • 新增皮肤:实现一个新的 Skin 即可,无需修改工厂与产品的接口。
  • 一致性保证:
    • 通过同一工厂创建的产品天然属于同一产品族,确保交互风格一致。
  • 注意事项:
    • setSkin 只影响之后创建的新组件,已创建实例不受影响。如果需要动态主题应用到已存在组件,可在产品中持有可变的 Skin 引用并提供刷新机制(视项目需求选择)。
    • 产品接口应稳定,新增产品类型(如 Checkbox)需要修改工厂接口与所有具体工厂的实现,需评估对现有代码的影响。

优缺点分析

  • 优点:
    • 保证同一产品族内组件的一致性与兼容性
    • 客户端与具体产品解耦,便于在运行时切换平台与皮肤
    • 易于扩展新平台或新皮肤,符合开闭原则(对扩展开放,对修改关闭)
    • 通过引入 Skin 策略,避免平台×皮肤的组合爆炸
  • 缺点:
    • 新增产品类型(例如新增 Checkbox)需要修改抽象工厂接口,并在所有具体工厂中实现,改动面较广
    • 类和接口数量较多,初期理解与维护成本略高
    • 若主题需要动态作用于已创建实例,需要额外的刷新机制或观察者支持,增加实现复杂度

使用建议:

  • 当需要在多个平台(或上下文)下提供一致的组件族,并支持主题切换时优先考虑抽象工厂。
  • 将“平台差异”与“皮肤差异”解耦:平台由具体工厂决定,皮肤由 Skin 策略注入,既保持一致性又避免类爆炸。

设计模式概述

  • 模式类型:行为型
  • 模式定义:策略模式将一组可互换的算法封装为独立的策略类,并在运行时依据上下文或配置选择具体策略,从而在不修改客户端代码的情况下扩展或切换算法。
  • 适用场景:
    • 需要在运行时根据会员等级、渠道、活动配置灵活切换不同的结算算法
    • 算法(如满减、阶梯折扣、优惠券叠加)可以独立变化、频繁更改或扩展
    • 需要通过配置组合多个折扣策略并控制顺序

核心角色

角色 职责说明
Strategy(折扣策略接口) 定义统一的折扣计算方法,输入当前应付金额和订单上下文,输出新的应付金额
ConcreteStrategy(具体策略) 满减策略、阶梯折扣策略、优惠券叠加策略等,分别实现各自算法
Context(策略上下文/容器) 维护策略注册表,根据配置选择并按序应用多个策略
OrderContext(业务上下文) 封装订单金额、会员等级、渠道、活动及规则、优惠券等业务数据
Factory/Registry(策略注册表) 管理策略的注册与查找,支持通过配置动态扩展与组合策略

Java代码实现

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * 策略模式示例:电商结算根据会员等级、活动与渠道切换折扣算法(满减、阶梯折扣、优惠券叠加)
 * 说明:
 * 1) DiscountStrategy 定义统一策略接口,每个策略实现 apply 方法;
 * 2) DiscountCalculator 作为上下文,持有策略注册表并按配置顺序应用策略;
 * 3) OrderContext 封装业务数据(金额、会员、渠道、规则、优惠券等);
 * 4) 通过注册表和策略编码实现运行期灵活组合与扩展。
 */
public class StrategyPatternEcommerceDemo {

    public static void main(String[] args) {
        // 1. 构建策略上下文并注册策略(可通过配置或依赖注入完成)
        DiscountCalculator calculator = new DiscountCalculator();
        calculator.register(new FullReductionStrategy());
        calculator.register(new TieredDiscountStrategy());
        calculator.register(new CouponStackStrategy());

        // 2. 构建订单上下文(模拟来自业务参数与配置中心)
        OrderContext ctx = new OrderContext();
        ctx.setOriginalAmount(new BigDecimal("688.00"));
        ctx.setMemberLevel(MemberLevel.GOLD);
        ctx.setChannel(Channel.APP);

        // 2.1 活动规则:满减(满300减40,按倍数叠加)
        FullReductionRule fr = new FullReductionRule(new BigDecimal("300"), new BigDecimal("40"), true);
        fr.setApplicableChannels(EnumSet.allOf(Channel.class));
        fr.setMinMemberLevel(MemberLevel.NORMAL);
        ctx.setFullReductionRule(fr);

        // 2.2 活动规则:阶梯折扣(满300打九折;满500打8.5折)
        TieredDiscountRule tr = new TieredDiscountRule();
        tr.addTier(new TieredDiscountRule.Tier(new BigDecimal("300"), new BigDecimal("0.90")));
        tr.addTier(new TieredDiscountRule.Tier(new BigDecimal("500"), new BigDecimal("0.85")));
        tr.setApplicableChannels(EnumSet.allOf(Channel.class));
        tr.setMinMemberLevel(MemberLevel.NORMAL);
        ctx.setTieredDiscountRule(tr);

        // 2.3 优惠券:满100减20(APP/H5),以及9折封顶50(仅APP)
        List<Coupon> coupons = new ArrayList<>();
        Coupon c1 = Coupon.fixAmount("满100减20券", new BigDecimal("20"), new BigDecimal("100"));
        c1.setApplicableChannels(EnumSet.of(Channel.APP, Channel.H5));
        coupons.add(c1);

        Coupon c2 = Coupon.percentWithCap("9折券封顶50", new BigDecimal("0.90"), new BigDecimal("50"), BigDecimal.ZERO);
        c2.setApplicableChannels(EnumSet.of(Channel.APP));
        coupons.add(c2);

        ctx.setCoupons(coupons);

        // 2.4 配置本次结算启用的策略及顺序(可来自配置中心/数据库)
        ctx.setStrategyCodes(Arrays.asList(
                FullReductionStrategy.CODE,
                TieredDiscountStrategy.CODE,
                CouponStackStrategy.CODE
        ));

        // 3. 计算应付金额
        BigDecimal payable = calculator.calculatePayable(ctx);

        // 4. 打印结果
        System.out.println("原价: " + scaleMoney(ctx.getOriginalAmount()));
        System.out.println("渠道: " + ctx.getChannel() + ",会员: " + ctx.getMemberLevel());
        System.out.println("应付: " + scaleMoney(payable));
    }

    // 金额统一保留两位小数
    private static BigDecimal scaleMoney(BigDecimal v) {
        return v.setScale(2, RoundingMode.HALF_UP);
    }

    // ========== 基础枚举 ==========
    enum MemberLevel {
        NORMAL, SILVER, GOLD, PLATINUM
    }

    enum Channel {
        APP, H5, WECHAT, PC
    }

    // ========== 订单上下文 ==========
    static class OrderContext {
        private BigDecimal originalAmount;
        private MemberLevel memberLevel;
        private Channel channel;

        private FullReductionRule fullReductionRule;
        private TieredDiscountRule tieredDiscountRule;
        private List<Coupon> coupons = Collections.emptyList();

        // 本次结算启用的策略编码(顺序即应用顺序)
        private List<String> strategyCodes = Collections.emptyList();

        public BigDecimal getOriginalAmount() {
            return originalAmount;
        }

        public void setOriginalAmount(BigDecimal originalAmount) {
            this.originalAmount = originalAmount;
        }

        public MemberLevel getMemberLevel() {
            return memberLevel;
        }

        public void setMemberLevel(MemberLevel memberLevel) {
            this.memberLevel = memberLevel;
        }

        public Channel getChannel() {
            return channel;
        }

        public void setChannel(Channel channel) {
            this.channel = channel;
        }

        public FullReductionRule getFullReductionRule() {
            return fullReductionRule;
        }

        public void setFullReductionRule(FullReductionRule fullReductionRule) {
            this.fullReductionRule = fullReductionRule;
        }

        public TieredDiscountRule getTieredDiscountRule() {
            return tieredDiscountRule;
        }

        public void setTieredDiscountRule(TieredDiscountRule tieredDiscountRule) {
            this.tieredDiscountRule = tieredDiscountRule;
        }

        public List<Coupon> getCoupons() {
            return coupons;
        }

        public void setCoupons(List<Coupon> coupons) {
            this.coupons = coupons != null ? coupons : Collections.emptyList();
        }

        public List<String> getStrategyCodes() {
            return strategyCodes;
        }

        public void setStrategyCodes(List<String> strategyCodes) {
            this.strategyCodes = strategyCodes != null ? strategyCodes : Collections.emptyList();
        }
    }

    // ========== 策略接口与上下文 ==========
    interface DiscountStrategy {
        // 每个策略的唯一编码,便于注册和配置引用
        String code();

        /**
         * 应用策略,输入:当前应付金额与订单上下文;输出:策略处理后的新应付金额
         * 注意:策略应保证幂等性与边界安全,不得返回负数
         */
        BigDecimal apply(BigDecimal currentPayable, OrderContext ctx);
    }

    /**
     * 策略上下文:维护策略注册表,按配置顺序应用策略
     */
    static class DiscountCalculator {
        private final Map<String, DiscountStrategy> registry = new HashMap<>();

        public void register(DiscountStrategy strategy) {
            if (strategy == null || strategy.code() == null) return;
            registry.put(strategy.code(), strategy);
        }

        public BigDecimal calculatePayable(OrderContext ctx) {
            Objects.requireNonNull(ctx, "OrderContext cannot be null");
            if (ctx.getOriginalAmount() == null) {
                throw new IllegalArgumentException("Original amount is required");
            }
            BigDecimal payable = ctx.getOriginalAmount();

            List<String> codes = ctx.getStrategyCodes();
            if (codes == null || codes.isEmpty()) {
                return nonNegative(payable);
            }
            for (String code : codes) {
                DiscountStrategy strategy = registry.get(code);
                if (strategy == null) {
                    // 未注册的策略可选择记录日志或忽略,这里选择忽略
                    continue;
                }
                payable = strategy.apply(payable, ctx);
            }
            return nonNegative(payable);
        }

        private BigDecimal nonNegative(BigDecimal v) {
            if (v == null) return BigDecimal.ZERO;
            return v.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : v;
        }
    }

    // ========== 满减规则与策略 ==========
    static class FullReductionRule {
        private boolean enabled = true;
        private BigDecimal threshold;           // 触发门槛:满 X 元
        private BigDecimal discountPerThreshold; // 每次减 Y 元
        private boolean multiple;               // 是否按倍数叠加:每满 X 减 Y
        private EnumSet<Channel> applicableChannels = EnumSet.allOf(Channel.class);
        private MemberLevel minMemberLevel = MemberLevel.NORMAL;

        public FullReductionRule(BigDecimal threshold, BigDecimal discountPerThreshold, boolean multiple) {
            this.threshold = threshold;
            this.discountPerThreshold = discountPerThreshold;
            this.multiple = multiple;
        }

        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }

        public BigDecimal getThreshold() {
            return threshold;
        }

        public BigDecimal getDiscountPerThreshold() {
            return discountPerThreshold;
        }

        public boolean isMultiple() {
            return multiple;
        }

        public EnumSet<Channel> getApplicableChannels() {
            return applicableChannels;
        }

        public void setApplicableChannels(EnumSet<Channel> applicableChannels) {
            this.applicableChannels = applicableChannels != null ? applicableChannels : EnumSet.noneOf(Channel.class);
        }

        public MemberLevel getMinMemberLevel() {
            return minMemberLevel;
        }

        public void setMinMemberLevel(MemberLevel minMemberLevel) {
            this.minMemberLevel = minMemberLevel != null ? minMemberLevel : MemberLevel.NORMAL;
        }
    }

    static class FullReductionStrategy implements DiscountStrategy {
        public static final String CODE = "FULL_REDUCTION";

        @Override
        public String code() {
            return CODE;
        }

        @Override
        public BigDecimal apply(BigDecimal currentPayable, OrderContext ctx) {
            FullReductionRule rule = ctx.getFullReductionRule();
            if (rule == null || !rule.isEnabled()) return currentPayable;
            if (!rule.getApplicableChannels().contains(ctx.getChannel())) return currentPayable;
            if (!levelEnough(ctx.getMemberLevel(), rule.getMinMemberLevel())) return currentPayable;

            BigDecimal payable = currentPayable;
            BigDecimal threshold = rule.getThreshold();
            BigDecimal per = rule.getDiscountPerThreshold();

            if (threshold == null || per == null) return currentPayable;
            if (threshold.compareTo(BigDecimal.ZERO) <= 0 || per.compareTo(BigDecimal.ZERO) <= 0) {
                return currentPayable;
            }

            BigDecimal discount = BigDecimal.ZERO;
            if (payable.compareTo(threshold) >= 0) {
                if (rule.isMultiple()) {
                    // 按倍数叠加:每满 X 减 Y
                    BigDecimal times = payable.divide(threshold, 0, RoundingMode.DOWN);
                    discount = per.multiply(times);
                } else {
                    // 仅触发一次
                    discount = per;
                }
            }
            BigDecimal result = payable.subtract(discount);
            return result.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : result;
        }
    }

    // ========== 阶梯折扣规则与策略 ==========
    static class TieredDiscountRule {
        static class Tier {
            private final BigDecimal minAmount;   // 门槛:>= minAmount
            private final BigDecimal discountRate; // 折扣率,如 0.90 表示 9 折

            public Tier(BigDecimal minAmount, BigDecimal discountRate) {
                this.minAmount = minAmount;
                this.discountRate = discountRate;
            }
        }

        private boolean enabled = true;
        private final List<Tier> tiers = new ArrayList<>();
        private EnumSet<Channel> applicableChannels = EnumSet.allOf(Channel.class);
        private MemberLevel minMemberLevel = MemberLevel.NORMAL;

        public void addTier(Tier tier) {
            if (tier != null) {
                tiers.add(tier);
            }
        }

        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }

        public List<Tier> getTiers() {
            return tiers;
        }

        public EnumSet<Channel> getApplicableChannels() {
            return applicableChannels;
        }

        public void setApplicableChannels(EnumSet<Channel> applicableChannels) {
            this.applicableChannels = applicableChannels != null ? applicableChannels : EnumSet.noneOf(Channel.class);
        }

        public MemberLevel getMinMemberLevel() {
            return minMemberLevel;
        }

        public void setMinMemberLevel(MemberLevel minMemberLevel) {
            this.minMemberLevel = minMemberLevel != null ? minMemberLevel : MemberLevel.NORMAL;
        }
    }

    static class TieredDiscountStrategy implements DiscountStrategy {
        public static final String CODE = "TIERED_DISCOUNT";

        @Override
        public String code() {
            return CODE;
        }

        @Override
        public BigDecimal apply(BigDecimal currentPayable, OrderContext ctx) {
            TieredDiscountRule rule = ctx.getTieredDiscountRule();
            if (rule == null || !rule.isEnabled()) return currentPayable;
            if (!rule.getApplicableChannels().contains(ctx.getChannel())) return currentPayable;
            if (!levelEnough(ctx.getMemberLevel(), rule.getMinMemberLevel())) return currentPayable;

            if (rule.getTiers().isEmpty()) return currentPayable;

            // 选取满足门槛的最大档位
            BigDecimal rate = null;
            BigDecimal payable = currentPayable;

            // 为确保顺序正确,按门槛从小到大遍历,取最后一个满足的档位
            List<TieredDiscountRule.Tier> tiers = new ArrayList<>(rule.getTiers());
            tiers.sort(new Comparator<TieredDiscountRule.Tier>() {
                @Override
                public int compare(TieredDiscountRule.Tier o1, TieredDiscountRule.Tier o2) {
                    return o1.minAmount.compareTo(o2.minAmount);
                }
            });

            for (TieredDiscountRule.Tier t : tiers) {
                if (payable.compareTo(t.minAmount) >= 0) {
                    rate = t.discountRate;
                }
            }
            if (rate == null) return currentPayable;
            if (rate.compareTo(BigDecimal.ZERO) <= 0 || rate.compareTo(BigDecimal.ONE) > 0) {
                // 合法性保护:折扣应在 (0,1] 区间
                return currentPayable;
            }
            BigDecimal result = payable.multiply(rate);
            // 金额计算结果保留两位
            return result.setScale(2, RoundingMode.HALF_UP);
        }
    }

    // ========== 优惠券模型与策略 ==========
    enum CouponType {
        FIX_AMOUNT,           // 固定立减:减 fixedAmount,需满足 thresholdAmount
        PERCENT_WITH_CAP      // 折扣券:按 percent 折扣,最多减 maxDeduction,可设门槛 thresholdAmount
    }

    static class Coupon {
        private boolean enabled = true;
        private String name;
        private CouponType type;

        // FIX_AMOUNT
        private BigDecimal fixedAmount = BigDecimal.ZERO;
        // PERCENT_WITH_CAP
        private BigDecimal percent = BigDecimal.ONE; // 0.90 = 9折
        private BigDecimal maxDeduction = BigDecimal.ZERO;

        // 通用门槛:达到该金额才可用(在当前应付金额基础上判断)
        private BigDecimal thresholdAmount = BigDecimal.ZERO;

        private EnumSet<Channel> applicableChannels = EnumSet.allOf(Channel.class);
        private MemberLevel minMemberLevel = MemberLevel.NORMAL;

        public static Coupon fixAmount(String name, BigDecimal fixedAmount, BigDecimal thresholdAmount) {
            Coupon c = new Coupon();
            c.name = name;
            c.type = CouponType.FIX_AMOUNT;
            c.fixedAmount = notNull(fixedAmount);
            c.thresholdAmount = notNull(thresholdAmount);
            return c;
        }

        public static Coupon percentWithCap(String name, BigDecimal percent, BigDecimal maxDeduction, BigDecimal thresholdAmount) {
            Coupon c = new Coupon();
            c.name = name;
            c.type = CouponType.PERCENT_WITH_CAP;
            c.percent = notNull(percent);
            c.maxDeduction = notNull(maxDeduction);
            c.thresholdAmount = notNull(thresholdAmount);
            return c;
        }

        public boolean isEnabled() {
            return enabled;
        }

        public void setEnabled(boolean enabled) {
            this.enabled = enabled;
        }

        public String getName() {
            return name;
        }

        public CouponType getType() {
            return type;
        }

        public BigDecimal getFixedAmount() {
            return fixedAmount;
        }

        public BigDecimal getPercent() {
            return percent;
        }

        public BigDecimal getMaxDeduction() {
            return maxDeduction;
        }

        public BigDecimal getThresholdAmount() {
            return thresholdAmount;
        }

        public EnumSet<Channel> getApplicableChannels() {
            return applicableChannels;
        }

        public void setApplicableChannels(EnumSet<Channel> applicableChannels) {
            this.applicableChannels = applicableChannels != null ? applicableChannels : EnumSet.noneOf(Channel.class);
        }

        public MemberLevel getMinMemberLevel() {
            return minMemberLevel;
        }

        public void setMinMemberLevel(MemberLevel minMemberLevel) {
            this.minMemberLevel = minMemberLevel != null ? minMemberLevel : MemberLevel.NORMAL;
        }
    }

    static class CouponStackStrategy implements DiscountStrategy {
        public static final String CODE = "COUPON_STACK";

        @Override
        public String code() {
            return CODE;
        }

        @Override
        public BigDecimal apply(BigDecimal currentPayable, OrderContext ctx) {
            List<Coupon> coupons = ctx.getCoupons();
            if (coupons == null || coupons.isEmpty()) return currentPayable;

            BigDecimal payable = currentPayable;

            // 约定:先应用折扣券(PERCENT_WITH_CAP),再应用固定立减券(FIX_AMOUNT)
            List<Coupon> percentCoupons = new ArrayList<>();
            List<Coupon> fixedCoupons = new ArrayList<>();
            for (Coupon c : coupons) {
                if (c == null || !c.isEnabled()) continue;
                if (!c.getApplicableChannels().contains(ctx.getChannel())) continue;
                if (!levelEnough(ctx.getMemberLevel(), c.getMinMemberLevel())) continue;
                if (c.getType() == CouponType.PERCENT_WITH_CAP) percentCoupons.add(c);
                if (c.getType() == CouponType.FIX_AMOUNT) fixedCoupons.add(c);
            }

            // 折扣券
            for (Coupon c : percentCoupons) {
                if (payable.compareTo(c.getThresholdAmount()) < 0) continue;
                BigDecimal percent = c.getPercent();
                if (percent.compareTo(BigDecimal.ZERO) <= 0 || percent.compareTo(BigDecimal.ONE) > 0) continue;

                BigDecimal discounted = payable.multiply(percent).setScale(2, RoundingMode.HALF_UP);
                BigDecimal deduction = payable.subtract(discounted);

                // 封顶保护
                if (c.getMaxDeduction() != null && deduction.compareTo(c.getMaxDeduction()) > 0) {
                    deduction = c.getMaxDeduction();
                }
                payable = payable.subtract(deduction);
                if (payable.compareTo(BigDecimal.ZERO) < 0) {
                    payable = BigDecimal.ZERO;
                    break;
                }
            }

            // 固定立减券
            for (Coupon c : fixedCoupons) {
                if (payable.compareTo(c.getThresholdAmount()) < 0) continue;
                BigDecimal fa = c.getFixedAmount();
                if (fa == null || fa.compareTo(BigDecimal.ZERO) <= 0) continue;

                payable = payable.subtract(fa);
                if (payable.compareTo(BigDecimal.ZERO) < 0) {
                    payable = BigDecimal.ZERO;
                    break;
                }
            }

            return payable;
        }
    }

    // ========== 通用小工具 ==========
    private static boolean levelEnough(MemberLevel actual, MemberLevel min) {
        if (actual == null || min == null) return false;
        return actual.ordinal() >= min.ordinal();
    }

    private static BigDecimal notNull(BigDecimal v) {
        return v != null ? v : BigDecimal.ZERO;
    }
}

实现要点

  • 策略接口统一:DiscountStrategy.apply 接收当前应付金额与 OrderContext,返回新的应付金额,便于顺序叠加多个策略。
  • 策略注册表:通过 DiscountCalculator.register 进行策略注册;通过策略编码(如 FULL_REDUCTION、TIERED_DISCOUNT、COUPON_STACK)在运行期按配置顺序动态组合。
  • 业务上下文解耦:OrderContext 承载订单金额、会员等级、渠道、活动规则与优惠券等数据,策略读取上下文所需信息,算法与数据解耦。
  • 满减策略:支持“满X减Y”与“每满X减Y按倍数叠加”,支持按渠道/会员启用。
  • 阶梯折扣策略:支持多档位门槛,选择满足条件的最高档位折扣率,结果按两位小数四舍五入。
  • 优惠券叠加策略:按固定顺序“先折扣券(封顶)再固定立减券”,并校验渠道、会员门槛与使用门槛;保证不产生负值。
  • 金额处理与边界安全:统一使用 BigDecimal,重要步骤 setScale(2, HALF_UP),并对负值进行钳制。
  • 开闭原则:新增策略仅需实现 DiscountStrategy 并通过 register 注册,无需改动现有策略与上下文。
  • 配置驱动:ctx.setStrategyCodes 指定策略启用与顺序,可由配置中心/数据库下发;规则与券也可配置化加载。
  • 可测试性:各策略为纯函数式实现(无副作用),易于单元测试与联调。

优缺点分析

  • 优点:
    • 算法解耦:各类折扣(满减、阶梯、优惠券)独立实现,互不影响。
    • 易于扩展:新增折扣类型仅需新增策略类并注册,符合开闭原则。
    • 运行期可配置:通过策略编码与顺序控制,按渠道/会员动态组合算法。
    • 易于测试:策略具备良好可测试性,可针对每个策略编写单测。
  • 缺点:
    • 策略数量增多:业务复杂时策略类较多,需要良好的命名与目录管理。
    • 组合顺序复杂:多策略叠加存在顺序敏感性,需要统一规范和配置校验。
    • 跨策略约束:某些业务规则(如不可同时使用)需额外的组合约束逻辑,可能引入额外管理层(如策略编排/规则引擎)。

说明:本示例保证代码完整且可编译运行,使用标准语法与清晰注释,适合在实际项目中作为策略模式在电商结算场景的参考实现。

设计模式概述

  • 模式类型:行为型
  • 模式定义:责任链模式通过将请求沿着处理者链传递,使多个处理者有机会处理该请求,从而实现请求发送者与接收者之间的解耦。可在运行时灵活组合、插拔和调整处理顺序。
  • 适用场景:
    • 需要对一个请求执行一系列的校验或处理,且步骤可插拔、可调整顺序
    • 各处理步骤彼此独立,职责清晰
    • 希望统一异常处理和日志输出,简化横切关注点

核心角色

角色 职责说明
Handler(抽象处理者) 定义处理请求的接口与链路转发逻辑,内置统一日志与异常包装
ConcreteHandler(具体处理者) 实现具体的处理逻辑(库存校验、黑名单过滤、风控评分、限购规则)
HandlerChain(处理链) 负责组装和执行处理者链,支持插拔与顺序调整
Context(上下文) 封装请求数据及处理过程中的中间状态(如风险分)
Request(请求对象) 订单提交请求的基本字段(用户、商品、数量)
BizException / ErrorCode 统一业务异常与错误码定义
Service(领域服务) 抽象外部依赖(库存、黑名单、风控、限购)并提供简化实现

Java代码实现

import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * 责任链模式 - 订单提交校验示例(简化版)
 * 校验步骤:库存校验 -> 黑名单过滤 -> 风控评分 -> 限购规则
 * 特点:可插拔、可调整顺序、统一异常与日志
 */
public class OrderSubmitChainDemo {

    // ===================== 统一异常与错误码 =====================
    enum ErrorCode {
        OUT_OF_STOCK,
        BLACKLISTED,
        HIGH_RISK,
        PURCHASE_LIMIT_EXCEEDED,
        SYSTEM_ERROR
    }

    static class BizException extends RuntimeException {
        private final ErrorCode errorCode;

        public BizException(ErrorCode code, String message) {
            super(message);
            this.errorCode = code;
        }

        public BizException(ErrorCode code, String message, Throwable cause) {
            super(message, cause);
            this.errorCode = code;
        }

        public ErrorCode getErrorCode() {
            return errorCode;
        }
    }

    // ===================== 请求、上下文与结果 =====================
    static class OrderSubmitRequest {
        private final String userId;
        private final String productId;
        private final int quantity;

        public OrderSubmitRequest(String userId, String productId, int quantity) {
            this.userId = userId;
            this.productId = productId;
            this.quantity = quantity;
        }

        public String getUserId() { return userId; }
        public String getProductId() { return productId; }
        public int getQuantity() { return quantity; }
    }

    static class OrderContext {
        private final OrderSubmitRequest request;
        // 中间产物:例如风控评分
        private int riskScore;

        public OrderContext(OrderSubmitRequest request) {
            this.request = request;
        }

        public OrderSubmitRequest getRequest() { return request; }
        public int getRiskScore() { return riskScore; }
        public void setRiskScore(int riskScore) { this.riskScore = riskScore; }
    }

    static class Result {
        private boolean success;
        private String message;
        private ErrorCode errorCode;

        public static Result ok() {
            Result r = new Result();
            r.success = true;
            r.message = "OK";
            return r;
        }

        public static Result fail(ErrorCode code, String message) {
            Result r = new Result();
            r.success = false;
            r.errorCode = code;
            r.message = message;
            return r;
        }

        @Override
        public String toString() {
            return "Result{" +
                    "success=" + success +
                    ", message='" + message + '\'' +
                    ", errorCode=" + errorCode +
                    '}';
        }
    }

    // ===================== 抽象处理者与处理链 =====================
    interface Handler {
        String name();
        void setNext(Handler next);
        void handle(OrderContext ctx);
    }

    static abstract class AbstractHandler implements Handler {
        protected final Logger log = Logger.getLogger(getClass().getName());
        private Handler next;

        @Override
        public void setNext(Handler next) {
            this.next = next;
        }

        @Override
        public String name() {
            return getClass().getSimpleName();
        }

        /**
         * 统一模板方法:日志 + 异常包装 + 链路透传
         */
        @Override
        public final void handle(OrderContext ctx) {
            long start = System.currentTimeMillis();
            log.info(() -> "[START] " + name() + ", req=" + brief(ctx.getRequest()));
            try {
                doHandle(ctx); // 具体处理
                log.info(() -> "[PASS]  " + name() + ", cost=" + (System.currentTimeMillis() - start) + "ms");
                if (next != null) {
                    next.handle(ctx);
                }
            } catch (BizException be) {
                log.log(Level.WARNING, "[BIZ-ERROR] " + name() + " -> " + be.getErrorCode() + ": " + be.getMessage());
                throw be;
            } catch (Exception e) {
                log.log(Level.SEVERE, "[SYS-ERROR] " + name() + " -> " + e.getMessage(), e);
                throw new BizException(ErrorCode.SYSTEM_ERROR, "System error in " + name(), e);
            }
        }

        protected abstract void doHandle(OrderContext ctx);

        private static String brief(OrderSubmitRequest r) {
            return "{user=" + r.getUserId() + ", product=" + r.getProductId() + ", qty=" + r.getQuantity() + "}";
        }
    }

    static class HandlerChain {
        private final Handler head;

        private HandlerChain(Handler head) {
            this.head = head;
        }

        public void execute(OrderContext ctx) {
            if (head != null) {
                head.handle(ctx);
            }
        }

        public static class Builder {
            private final List<Handler> list = new ArrayList<>();

            public Builder add(Handler handler) {
                list.add(handler);
                return this;
            }

            public HandlerChain build() {
                if (list.isEmpty()) return new HandlerChain(null);
                for (int i = 0; i < list.size() - 1; i++) {
                    list.get(i).setNext(list.get(i + 1));
                }
                return new HandlerChain(list.get(0));
            }
        }
    }

    // ===================== 领域服务(示例实现) =====================
    interface InventoryService {
        int getAvailableStock(String productId);
    }

    interface BlacklistService {
        boolean isBlacklisted(String userId);
    }

    interface RiskService {
        int calcRiskScore(String userId);
    }

    interface PurchaseLimitService {
        boolean exceedsLimit(String userId, String productId, int quantity);
    }

    // 简化的内存实现
    static class InMemoryInventoryService implements InventoryService {
        private final Map<String, Integer> stockMap;

        public InMemoryInventoryService(Map<String, Integer> stockMap) {
            this.stockMap = stockMap;
        }

        @Override
        public int getAvailableStock(String productId) {
            return stockMap.getOrDefault(productId, 0);
        }
    }

    static class InMemoryBlacklistService implements BlacklistService {
        private final Set<String> blackSet;

        public InMemoryBlacklistService(Set<String> blackSet) {
            this.blackSet = blackSet;
        }

        @Override
        public boolean isBlacklisted(String userId) {
            return blackSet.contains(userId);
        }
    }

    static class InMemoryRiskService implements RiskService {
        private final Map<String, Integer> riskScoreMap;
        public InMemoryRiskService(Map<String, Integer> riskScoreMap) {
            this.riskScoreMap = riskScoreMap;
        }
        @Override
        public int calcRiskScore(String userId) {
            return riskScoreMap.getOrDefault(userId, 0);
        }
    }

    static class SimplePurchaseLimitService implements PurchaseLimitService {
        private final Map<String, Integer> perUserProductLimit; // key: userId#productId

        public SimplePurchaseLimitService(Map<String, Integer> perUserProductLimit) {
            this.perUserProductLimit = perUserProductLimit;
        }

        @Override
        public boolean exceedsLimit(String userId, String productId, int quantity) {
            String key = userId + "#" + productId;
            int limit = perUserProductLimit.getOrDefault(key, Integer.MAX_VALUE);
            return quantity > limit;
        }
    }

    // ===================== 具体处理者实现 =====================
    static class InventoryCheckHandler extends AbstractHandler {
        private final InventoryService inventoryService;

        public InventoryCheckHandler(InventoryService inventoryService) {
            this.inventoryService = inventoryService;
        }

        @Override
        protected void doHandle(OrderContext ctx) {
            OrderSubmitRequest req = ctx.getRequest();
            int stock = inventoryService.getAvailableStock(req.getProductId());
            if (stock < req.getQuantity()) {
                throw new BizException(
                        ErrorCode.OUT_OF_STOCK,
                        "Insufficient stock. required=" + req.getQuantity() + ", available=" + stock
                );
            }
        }
    }

    static class BlacklistCheckHandler extends AbstractHandler {
        private final BlacklistService blacklistService;

        public BlacklistCheckHandler(BlacklistService blacklistService) {
            this.blacklistService = blacklistService;
        }

        @Override
        protected void doHandle(OrderContext ctx) {
            String userId = ctx.getRequest().getUserId();
            if (blacklistService.isBlacklisted(userId)) {
                throw new BizException(
                        ErrorCode.BLACKLISTED,
                        "User " + userId + " is in blacklist"
                );
            }
        }
    }

    static class RiskScoreHandler extends AbstractHandler {
        private final RiskService riskService;
        private final int threshold; // 风控阈值

        public RiskScoreHandler(RiskService riskService, int threshold) {
            this.riskService = riskService;
            this.threshold = threshold;
        }

        @Override
        protected void doHandle(OrderContext ctx) {
            String userId = ctx.getRequest().getUserId();
            int score = riskService.calcRiskScore(userId);
            ctx.setRiskScore(score);
            if (score >= threshold) {
                throw new BizException(
                        ErrorCode.HIGH_RISK,
                        "Risk score too high: " + score + ", threshold=" + threshold
                );
            }
        }
    }

    static class PurchaseLimitHandler extends AbstractHandler {
        private final PurchaseLimitService purchaseLimitService;

        public PurchaseLimitHandler(PurchaseLimitService purchaseLimitService) {
            this.purchaseLimitService = purchaseLimitService;
        }

        @Override
        protected void doHandle(OrderContext ctx) {
            OrderSubmitRequest req = ctx.getRequest();
            if (purchaseLimitService.exceedsLimit(req.getUserId(), req.getProductId(), req.getQuantity())) {
                throw new BizException(
                        ErrorCode.PURCHASE_LIMIT_EXCEEDED,
                        "Purchase limit exceeded for user=" + req.getUserId() + ", product=" + req.getProductId()
                );
            }
        }
    }

    // ===================== 示例运行 =====================
    public static void main(String[] args) {
        // 初始化日志级别(可选)
        Logger root = Logger.getLogger("");
        root.setLevel(Level.INFO);

        // 构造示例服务数据
        InventoryService inventoryService = new InMemoryInventoryService(new HashMap<String, Integer>() {{
            put("P1001", 5);
            put("P1002", 0);
        }});
        BlacklistService blacklistService = new InMemoryBlacklistService(new HashSet<>(Arrays.asList("U999")));
        RiskService riskService = new InMemoryRiskService(new HashMap<String, Integer>() {{
            put("U100", 30);
            put("U200", 85);
        }});
        PurchaseLimitService limitService = new SimplePurchaseLimitService(new HashMap<String, Integer>() {{
            put("U100#P1001", 3); // 用户U100对商品P1001限购3件
        }});

        // 构造处理器(可插拔)
        Handler inventory = new InventoryCheckHandler(inventoryService);
        Handler blacklist = new BlacklistCheckHandler(blacklistService);
        Handler risk     = new RiskScoreHandler(riskService, 60);
        Handler limit    = new PurchaseLimitHandler(limitService);

        // 组装处理链(可调整顺序)
        HandlerChain chain = new HandlerChain.Builder()
                .add(inventory) // 先校验库存
                .add(blacklist) // 再检查黑名单
                .add(risk)      // 再风控
                .add(limit)     // 再限购
                .build();

        // 示例请求(成功案例)
        OrderSubmitRequest reqOk = new OrderSubmitRequest("U100", "P1001", 2);
        Result resultOk;
        try {
            chain.execute(new OrderContext(reqOk));
            resultOk = Result.ok();
        } catch (BizException e) {
            resultOk = Result.fail(e.getErrorCode(), e.getMessage());
        }
        System.out.println("Submit result 1: " + resultOk);

        // 示例请求(失败案例:库存不足或高风险等)
        OrderSubmitRequest reqFail = new OrderSubmitRequest("U200", "P1001", 2); // 高风险用户
        Result resultFail;
        try {
            chain.execute(new OrderContext(reqFail));
            resultFail = Result.ok();
        } catch (BizException e) {
            resultFail = Result.fail(e.getErrorCode(), e.getMessage());
        }
        System.out.println("Submit result 2: " + resultFail);

        // 如需调整顺序或插拔某个步骤,只需更改构建器顺序或不添加即可
        // 例如:先做风控,再做库存
        HandlerChain altChain = new HandlerChain.Builder()
                .add(risk)
                .add(blacklist)
                .add(inventory)
                .add(limit)
                .build();

        try {
            altChain.execute(new OrderContext(reqOk));
            System.out.println("Alt chain: OK");
        } catch (BizException e) {
            System.out.println("Alt chain: FAIL -> " + e.getErrorCode() + ", " + e.getMessage());
        }
    }
}

实现要点

  • 抽象处理者模板方法
    • 在 AbstractHandler.handle 中统一做日志、异常包装与链路透传;具体逻辑在 doHandle 中实现,简化横切关注点的处理。
  • 可插拔与可调整顺序
    • HandlerChain.Builder 以列表顺序串联处理器;通过修改 add 的顺序或省略某个处理器实现插拔与重排。
  • 统一异常与错误码
    • 通过 BizException 和 ErrorCode 进行业务错误统一管理,上层只需捕获 BizException 生成统一返回。
  • 上下文共享中间结果
    • OrderContext 存储中间值(如风险分)以便后续处理器复用,避免重复计算或耦合。
  • 简化服务依赖
    • 使用内存 Map/Set 模拟外部服务,实际项目中替换为真实服务实现即可,处理器无需变更。

优缺点分析

  • 优点:
    • 解耦:请求发起方与各处理步骤解耦,新增/删除处理器对其他模块影响较小。
    • 可扩展:可在运行时按需组装链路,支持步骤的插拔与顺序调整。
    • 职责单一:每个处理器只关心自身逻辑,代码清晰、可测试性强。
    • 横切统一:通过模板方法统一日志与异常处理,降低重复代码。
  • 缺点:
    • 调试复杂:链路过长时定位问题需要依赖完善的日志与追踪。
    • 性能风险:不当的链路顺序可能造成不必要的开销(例如把昂贵步骤放在前面)。
    • 不保证处理:若所有处理器都通过但业务仍需其他保障,需确保链尾有默认处理或最终落地逻辑。

使用建议:在订单提交流程中,将副作用大、耗时长的步骤后置,将快速失败的步骤前置;通过配置或装配(如Spring配置)管理链路,便于动态调整和灰度。

示例详情

解决的问题

把“学会并正确落地设计模式”变成一次输入、完整产出的高效体验:只需给出模式名称、期望复杂度与业务场景,即可获得可直接粘贴运行的Java示例、清晰注释、角色关系与应用建议;在培训、评审、重构与面试准备等环节输出统一标准,减少沟通与返工;以结构化、可复用的结果沉淀团队实践库,提升交付质量与速度,缩短从方案到代码的路径,推动从试用到常态化使用与付费转化。

适用用户

Java开发工程师

从模式名称一键生成可运行示例,快速搭建新功能骨架;重构遗留模块时参考标准结构;准备面试与笔试,快速梳理实现思路与要点。

架构师与技术负责人

在评审会中用生成的角色分工与示例说明方案;对比多种模式的适配范围,做出取舍;沉淀团队统一代码模板与实践指南。

编程讲师与培训机构

快速产出课堂讲义与演示代码,按难度分层讲解;布置课后作业与参考答案;减少准备时间,提升课堂互动与学习投入。

特征总结

一键生成指定设计模式的Java代码示例,类与方法齐全、注释清晰,拿来即可运行与讲解。
自动给出核心角色与职责分工,帮助快速看清结构关系,减少摸索时间与沟通成本。
结合你的业务场景输出使用建议,提示何时使用、何时避免,避免过度设计与返工。
支持选择代码复杂度与风格,教学演示用简版,生产参考用标准版,随需切换。
输出实现要点与常见坑位清单,附上替代思路与注意事项,显著降低试错成本。
内置优缺点对比与适配范围说明,便于方案评审与技术说明会快速达成一致。
兼顾规范与可读性,统一命名与注释风格,方便团队直接纳入日常代码模板库。
提供典型调用示例与运行步骤,复制即可体验效果,节省搭建样例与演示准备时间。
支持多种设计模式横向对比与选型提示,需求变化时也能迅速调整实现路线。
适合面试突击与团队培训,快速生成讲义式内容,提高准备效率与学习效果。

如何使用购买的提示词模板

1. 直接在外部 Chat 应用中使用

将模板生成的提示词复制粘贴到您常用的 Chat 应用(如 ChatGPT、Claude 等),即可直接对话使用,无需额外开发。适合个人快速体验和轻量使用场景。

2. 发布为 API 接口调用

把提示词模板转化为 API,您的程序可任意修改模板参数,通过接口直接调用,轻松实现自动化与批量处理。适合开发者集成与业务系统嵌入。

3. 在 MCP Client 中配置使用

在 MCP client 中配置对应的 server 地址,让您的 AI 应用自动调用提示词模板。适合高级用户和团队协作,让提示词在不同 AI 工具间无缝衔接。

AI 提示词价格
¥20.00元
先用后买,用好了再付款,超安全!

您购买后可以获得什么

获得完整提示词模板
- 共 661 tokens
- 3 个可调节参数
{ 设计模式名称 } { 代码复杂度 } { 应用场景 }
获得社区贡献内容的使用权
- 精选社区优质案例,助您快速上手提示词
使用提示词兑换券,低至 ¥ 9.9
了解兑换券 →
限时半价

不要错过!

半价获取高级提示词-优惠即将到期

17
:
23
小时
:
59
分钟
:
59