如何移除代码中的if-else条件,实现支付逻辑动态扩展?
解决支付处理器硬编码判断的方案
你的问题核心是当前代码违反了开闭原则——新增支付方式必须修改核心业务逻辑(Store类),导致维护成本随扩展方法数量线性上升。下面给出几种落地性强的解决方案,按优先级排序:
1. 优先用「适配器模式+统一接口」(最推荐)
如果无法修改第三方支付处理器的代码(比如Stripe/Paypal是外部库),适配器模式能完美适配不同的方法签名,同时让核心业务逻辑摆脱类型判断。
步骤1:定义统一支付接口
先抽象出所有支付处理器的通用行为,把不同的参数封装到一个凭证类里:
// 统一支付接口 public interface IPaymentProcessor { void ProcessPayment(decimal amount, PaymentCredentials credentials); } // 通用支付凭证,包含所有可能需要的字段 public class PaymentCredentials { public string CardNumber { get; set; } // Stripe需要 public string Email { get; set; } // Paypal需要 public string Phone { get; set; } // 其他支付方式可能需要 }
步骤2:为每个支付处理器写适配器
适配器类实现统一接口,内部包装原处理器,把通用调用转换成对应处理器的特定方法:
// Stripe适配器 public class StripePaymentAdapter : IPaymentProcessor { private readonly StripePaymentProcessor _stripeProcessor; public StripePaymentAdapter(StripePaymentProcessor stripeProcessor) { _stripeProcessor = stripeProcessor; } public void ProcessPayment(decimal amount, PaymentCredentials credentials) { // 适配Stripe的Pay方法签名:Pay(decimal amount, string cardNumber) _stripeProcessor.Pay(amount, credentials.CardNumber); } } // Paypal适配器 public class PaypalPaymentAdapter : IPaymentProcessor { private readonly PaypalPaymentProcessor _paypalProcessor; public PaypalPaymentAdapter(PaypalPaymentProcessor paypalProcessor) { _paypalProcessor = paypalProcessor; } public void ProcessPayment(decimal amount, PaymentCredentials credentials) { // 适配Paypal的Pay方法签名:Pay(string email, decimal amount) _paypalProcessor.Pay(credentials.Email, amount); } }
步骤3:改造Store类
现在Store类只需要依赖统一接口,完全不用管具体是哪个支付处理器:
public class Store { public void ProcessPayment(IPaymentProcessor processor, decimal amount, PaymentCredentials credentials) { processor.ProcessPayment(amount, credentials); // 新增支付方式?只需要加对应的适配器,这里一行代码都不用改 } }
2. 结合工厂模式实现动态创建
如果需要根据配置或用户选择动态生成支付处理器,可以加一个简单的工厂类,把创建逻辑集中管理:
public static class PaymentProcessorFactory { // 注册所有支持的支付处理器 private static readonly Dictionary<string, Func<IPaymentProcessor>> _processorRegistry = new() { { "Stripe", () => new StripePaymentAdapter(new StripePaymentProcessor()) }, { "Paypal", () => new PaypalPaymentAdapter(new PaypalPaymentProcessor()) } }; public static IPaymentProcessor GetProcessor(string processorType) { if (_processorRegistry.TryGetValue(processorType, out var factory)) { return factory(); } throw new NotSupportedException($"不支持的支付方式:{processorType}"); } }
使用示例:
// 从配置或用户输入获取支付方式 var selectedProcessor = "Stripe"; var processor = PaymentProcessorFactory.GetProcessor(selectedProcessor); var store = new Store(); store.ProcessPayment(processor, 199.9m, new PaymentCredentials { CardNumber = "4111-1111-1111-1111" });
3. 极端场景下用反射(不推荐,仅作补充)
如果支付处理器数量极多,且方法签名无规律,不想写大量适配器,可以用反射动态调用方法。但要注意性能损耗和类型安全问题:
public class Store { public void ProcessPayment(object processor, decimal amount, Dictionary<string, object> paramsMap) { var method = processor.GetType().GetMethod("Pay"); if (method == null) throw new InvalidOperationException("支付处理器无Pay方法"); // 根据方法参数从paramsMap中提取对应值 var parameters = method.GetParameters() .Select(p => paramsMap[p.Name]) .ToArray(); method.Invoke(processor, parameters); } }
使用示例:
var stripe = new StripePaymentProcessor(); var store = new Store(); store.ProcessPayment(stripe, 99.9m, new Dictionary<string, object> { { "amount", 99.9m }, { "cardNumber", "4111-1111-1111-1111" } });
内容的提问来源于stack exchange,提问作者JohnJS
相关产品推荐
相关产品推荐

