策略模式和工厂模式中新增一个行为
前置:策略+工厂重构if
https://www.cnblogs.com/aeolian/p/18865859
🧠 策略类新增行为
在使用策略模式(配合工厂)管理“请款方式”时,若要为已有策略添加新的行为(比如 refund()
退款、queryStatus()
状态查询),可能面临接口设计和扩展性问题。
“添加一个行为”,不是“添加一个策略实现”。
• 已有策略类(比如 AliPay, WeChatPay);
• 想在这些类中统一增加一个新的方法,比如 refund()(退款)或者 queryStatus()(查询支付状态);
• 而不是新增一种支付方式。
✅ 方式一:直接在接口中新增方法
适合所有策略类都要实现这个新行为的情况。
public interface PaymentStrategy {
void pay(double amount);
void refund(double amount); // 新增方法
}
public class AliPay implements PaymentStrategy {
public void pay(double amount) {
// 支付逻辑
}
public void refund(double amount) {
// 退款逻辑
}
}
📌 优点:
• 明确、统一,调用方便;
• 类型安全,代码清晰。
⚠️ 缺点:
• 所有实现类都必须改;
• 如果某些类不支持该行为,只能抛异常或空实现,违背接口隔离原则。
✅ 方式二:接口分离 + 组合判断
若不是所有支付方式都支持新行为,可以将其拆成独立接口。
public interface Refundable {
void refund(double amount);
}
public class AliPay implements PaymentStrategy, Refundable {
public void pay(double amount) {
// ...
}
public void refund(double amount) {
// ...
}
}
调用端按需判断:
PaymentStrategy strategy = getStrategy();
if (strategy instanceof Refundable r) {
r.refund(100.0);
}
📌 优点:
• 遵循接口隔离原则;
• 不影响现有实现类;
• 拓展更灵活。
✅ 方式三:装饰器模式添加行为(不动原类)
如果不希望修改原有类结构,可用装饰器包裹原策略,添加额外行为。
public class RefundableWrapper implements PaymentStrategy {
private final PaymentStrategy delegate;
public RefundableWrapper(PaymentStrategy delegate) {
this.delegate = delegate;
}
@Override
public void pay(double amount) {
delegate.pay(amount);
}
public void refund(double amount) {
// 添加新行为,如退款、日志等
}
}
📌 优点:
• 不动原代码;
• 可动态叠加行为(如日志、监控、缓存);
• 拓展性强,适合 AOP 风格开发。
🧠 总结对比表:策略模式中添加新行为的三种方式
使用场景 | 推荐方式 | 优点 | 缺点 |
---|---|---|---|
所有策略类都必须支持该新行为 | ✅ 在接口中直接添加方法 | 明确统一、类型安全、调用方便 | 所有实现类都要改,可能违背接口隔离原则 |
只有部分策略类需要支持该新行为 | ✅ 拆分为单独接口 + 组合判断 | 拓展灵活,符合接口隔离原则,不影响其他类 | 需要额外进行类型判断(instanceof ) |
不希望动现有策略类,动态增强行为 | ✅ 使用装饰器模式(Wrapper) | 不动原代码、易于扩展、适合叠加日志/缓存/验证等功能 | 包装逻辑相对复杂、理解成本略高 |
🎯 小贴士:
- 如果你是在维护一个稳定系统,建议优先使用“组合 + 装饰器”方式;
- 如果你在重构或设计新系统,尽量遵循“接口分离”原则,提前预留行为扩展口;
- 不要害怕拆接口,也不要为了“统一”而强求所有类都支持不相关的行为。
✨ 提醒:策略模式的初衷是封装行为的变化,而不是一次性定死行为列表。当行为本身也在扩展,不要只想着“继承”,要用组合、拆分、装饰等方式以变应变。
如果这篇文章对你有用,可以关注本人微信公众号获取更多ヽ(^ω^)ノ ~
