热门角色不仅是灵感来源,更是你的效率助手。通过精挑细选的角色提示词,你可以快速生成高质量内容、提升创作灵感,并找到最契合你需求的解决方案。让创作更轻松,让价值更直接!
我们根据不同用户需求,持续更新角色库,让你总能找到合适的灵感入口。
本提示词专为Java开发者设计,能够根据指定的设计模式名称生成对应的Java代码实现示例。通过详细的代码注释、结构分析和应用场景说明,帮助开发者深入理解各种设计模式的实现原理和实际应用。输出内容包括完整的类结构定义、方法实现、设计模式核心要素解析以及典型使用场景介绍,确保代码符合Java开发规范和最佳实践。
| 角色 | 职责说明 |
|---|---|
| AbstractFactory(UIFactory) | 定义创建一组相关产品(按钮、输入框)的抽象接口,并允许设置皮肤(Skin) |
| ConcreteFactory(DesktopUIFactory、MobileUIFactory) | 具体工厂,按平台生成成套组件,且与当前皮肤组合输出外观 |
| AbstractProduct(Button、TextField) | 定义产品族中各个抽象产品的接口 |
| ConcreteProduct(DesktopButton、MobileButton、DesktopTextField、MobileTextField) | 平台相关的具体产品,实现渲染与交互逻辑,并受皮肤影响 |
| Skin(Skin、LightSkin、DarkSkin) | 皮肤/主题策略,提供颜色等视觉参数,便于工厂产品组合输出统一风格 |
| Client(AbstractFactoryDemo) | 客户端,依赖抽象工厂与抽象产品,通过切换工厂/皮肤达到平台与主题的替换 |
/**
* 抽象工厂模式示例
* 需求:桌面与移动端需统一主题与交互,抽象出按钮、输入框等控件族,按平台生成成套组件,支持更换皮肤与扩展。
*
* 说明:
* - 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.");
}
}
使用建议:
| 角色 | 职责说明 |
|---|---|
| Strategy(折扣策略接口) | 定义统一的折扣计算方法,输入当前应付金额和订单上下文,输出新的应付金额 |
| ConcreteStrategy(具体策略) | 满减策略、阶梯折扣策略、优惠券叠加策略等,分别实现各自算法 |
| Context(策略上下文/容器) | 维护策略注册表,根据配置选择并按序应用多个策略 |
| OrderContext(业务上下文) | 封装订单金额、会员等级、渠道、活动及规则、优惠券等业务数据 |
| Factory/Registry(策略注册表) | 管理策略的注册与查找,支持通过配置动态扩展与组合策略 |
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;
}
}
说明:本示例保证代码完整且可编译运行,使用标准语法与清晰注释,适合在实际项目中作为策略模式在电商结算场景的参考实现。
| 角色 | 职责说明 |
|---|---|
| Handler(抽象处理者) | 定义处理请求的接口与链路转发逻辑,内置统一日志与异常包装 |
| ConcreteHandler(具体处理者) | 实现具体的处理逻辑(库存校验、黑名单过滤、风控评分、限购规则) |
| HandlerChain(处理链) | 负责组装和执行处理者链,支持插拔与顺序调整 |
| Context(上下文) | 封装请求数据及处理过程中的中间状态(如风险分) |
| Request(请求对象) | 订单提交请求的基本字段(用户、商品、数量) |
| BizException / ErrorCode | 统一业务异常与错误码定义 |
| Service(领域服务) | 抽象外部依赖(库存、黑名单、风控、限购)并提供简化实现 |
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());
}
}
}
使用建议:在订单提交流程中,将副作用大、耗时长的步骤后置,将快速失败的步骤前置;通过配置或装配(如Spring配置)管理链路,便于动态调整和灰度。
把“学会并正确落地设计模式”变成一次输入、完整产出的高效体验:只需给出模式名称、期望复杂度与业务场景,即可获得可直接粘贴运行的Java示例、清晰注释、角色关系与应用建议;在培训、评审、重构与面试准备等环节输出统一标准,减少沟通与返工;以结构化、可复用的结果沉淀团队实践库,提升交付质量与速度,缩短从方案到代码的路径,推动从试用到常态化使用与付费转化。
从模式名称一键生成可运行示例,快速搭建新功能骨架;重构遗留模块时参考标准结构;准备面试与笔试,快速梳理实现思路与要点。
在评审会中用生成的角色分工与示例说明方案;对比多种模式的适配范围,做出取舍;沉淀团队统一代码模板与实践指南。
快速产出课堂讲义与演示代码,按难度分层讲解;布置课后作业与参考答案;减少准备时间,提升课堂互动与学习投入。
将模板生成的提示词复制粘贴到您常用的 Chat 应用(如 ChatGPT、Claude 等),即可直接对话使用,无需额外开发。适合个人快速体验和轻量使用场景。
把提示词模板转化为 API,您的程序可任意修改模板参数,通过接口直接调用,轻松实现自动化与批量处理。适合开发者集成与业务系统嵌入。
在 MCP client 中配置对应的 server 地址,让您的 AI 应用自动调用提示词模板。适合高级用户和团队协作,让提示词在不同 AI 工具间无缝衔接。
半价获取高级提示词-优惠即将到期