适用于支付模块的设计模式c#

当我通过设计模式概念学习时,我也希望使用适当的设计模式在我的项目中实现支付模块。 所以为此我创建了一些示例代码。

目前我有两个具体实施支付PayPalCredit Card 。 但具体实施将在项目中进一步增加。

付款服务

 public interface IPaymentService { void MakePayment(T type) where T : class; } 

信用卡和Pay Pal服务

 public class CreditCardPayment : IPaymentService { public void MakePayment(T type) where T : class { var creditCardModel = (CreditCardModel)(object)type; //Implementation CreditCardPayment } } class PayPalPayment : IPaymentService { public void MakePayment(T type) where T : class { var payPalModel = (PayPalModel)(object)type; //Further Implementation will goes here } } 

客户端代码实现

 var obj = GetPaymentOption(payType); obj.MakePayment(payPalModel); 

获得付款选项

 private static IPaymentService GetPaymentOption(PaymentType paymentType) { IPaymentService paymentService = null; switch (paymentType) { case PaymentType.PayPalPayment: paymentService = new PayPalPayment(); break; case PaymentType.CreditCardPayment: paymentService = new CreditCardPayment(); break; default: break; } return paymentService; } 

我想过使用策略设计模式来实现这些模块,并且我偏离了策略并最终采用了这种方式。

这是创建付款模块的正确方法吗? 是否有更好的方法来解决这种情况。 这是一种设计模式吗?

编辑:

客户代码:

 static void Main(string[] args) { PaymentStrategy paymentStrategy = null; paymentStrategy = new PaymentStrategy(GetPaymentOption((PaymentType)1)); paymentStrategy.Pay(new PayPalModel() { UserName = "", Password = "" }); paymentStrategy = new PaymentStrategy(GetPaymentOption((PaymentType)2)); paymentStrategy.Pay( new CreditCardModel() { CardHolderName = "Aakash" }); Console.ReadLine(); } 

战略:

 public class PaymentStrategy { private readonly IPaymentService paymentService; public PaymentStrategy(IPaymentService paymentService) { this.paymentService = paymentService; } public void Pay(T type) where T : class { paymentService.MakePayment(type); } } 

此更新是否与策略模式一致?

使用抽象工厂的一个主要缺点是它包含switch case语句。 这本质上意味着如果要添加支付服务,则必须更新工厂类中的代码。 这违反了开放封闭的委托人 ,该委托人声明实体应该开放以进行延期,但是关闭以进行修改。

请注意,出于同样的原因,使用Enum在支付提供商之间切换也存在问题。 这意味着每次添加或删除支付服务时,服务列表都必须更改。 更糟糕的是,支付服务可以从策略中删除,但即使它无效,仍然是它的Enum符号。

另一方面,使用策略模式不需要switch case语句。 因此,添加或删除付款服务时,现有类不会发生任何更改。 这一点以及支付选项的数量可能会限制在一个小的两位数的事实使得策略模式更适合这种情况。

接口

 // Empty interface just to ensure that we get a compile // error if we pass a model that does not belong to our // payment system. public interface IPaymentModel { } public interface IPaymentService { void MakePayment(T model) where T : IPaymentModel; bool AppliesTo(Type provider); } public interface IPaymentStrategy { void MakePayment(T model) where T : IPaymentModel; } 

楷模

 public class CreditCardModel : IPaymentModel { public string CardHolderName { get; set; } public string CardNumber { get; set; } public int ExpirtationMonth { get; set; } public int ExpirationYear { get; set; } } public class PayPalModel : IPaymentModel { public string UserName { get; set; } public string Password { get; set; } } 

付款服务抽象

这是一个抽象类,用于隐藏从IPaymentService实现中转换为具体模型类型的丑陋细节。

 public abstract class PaymentService : IPaymentService where TModel : IPaymentModel { public virtual bool AppliesTo(Type provider) { return typeof(TModel).Equals(provider); } public void MakePayment(T model) where T : IPaymentModel { MakePayment((TModel)(object)model); } protected abstract void MakePayment(TModel model); } 

支付服务实施

 public class CreditCardPayment : PaymentService { protected override void MakePayment(CreditCardModel model) { //Implementation CreditCardPayment } } public class PayPalPayment : PaymentService { protected override void MakePayment(PayPalModel model) { //Implementation PayPalPayment } } 

付款策略

这是将它们联系在一起的课程。 其主要目的是根据传递的模型类型提供支付服务的选择function。 但与此处的其他示例不同,它松散地耦合了IPaymentService实现,因此这里不直接引用它们。 这意味着无需更改设计,即可添加或删除支付提供商。

 public class PaymentStrategy : IPaymentStrategy { private readonly IEnumerable paymentServices; public PaymentStrategy(IEnumerable paymentServices) { if (paymentServices == null) throw new ArgumentNullException(nameof(paymentServices)); this.paymentServices = paymentServices; } public void MakePayment(T model) where T : IPaymentModel { GetPaymentService(model).MakePayment(model); } private IPaymentService GetPaymentService(T model) where T : IPaymentModel { var result = paymentServices.FirstOrDefault(p => p.AppliesTo(model.GetType())); if (result == null) { throw new InvalidOperationException( $"Payment service for {model.GetType().ToString()} not registered."); } return result; } } 

用法

 // I am showing this in code, but you would normally // do this with your DI container in your composition // root, and the instance would be created by injecting // it somewhere. var paymentStrategy = new PaymentStrategy( new IPaymentService[] { new CreditCardPayment(), // <-- inject any dependencies here new PayPalPayment() // <-- inject any dependencies here }); // Then once it is injected, you simply do this... var cc = new CreditCardModel() { CardHolderName = "Bob" }; paymentStrategy.MakePayment(cc); // Or this... var pp = new PayPalModel() { UserName = "Bob" }; paymentStrategy.MakePayment(pp); 

其他参考文献:

  • dependency injection统一 - 条件解析
  • 使用DI和IoC的工厂方法

这是您可以采取的一种方法。 从你的来源开始并没有太多东西,我真的重新考虑让MakePayment成为一个空虚,而不是像IPayResult。

 public interface IPayModel { } // Worth investigating into common shared methods and properties for this public interface IPaymentService { void MakePayment(IPayModel payModel); } public interface IPaymentService : IPaymentService where T : IPayModel { void MakePayment(T payModel); // Void here? Is the status of the payment saved on the concrete pay model? Why not an IPayResult? } public class CreditCardModel : IPayModel { public string CardHolderName { get; set; } } public class PayPalModel : IPayModel { public string UserName { get; set; } public string Password { get; set; } } public class CreditCardPayment : IPaymentService { public void MakePayment(CreditCardModel payModel) { //Implmentation CreditCardPayment } void IPaymentService.MakePayment(IPayModel payModel) { MakePayment(payModel as CreditCardModel); } } public class PayPalPayment : IPaymentService { public void MakePayment(PayPalModel payModel) { //Implmentation PayPalPayment } void IPaymentService.MakePayment(IPayModel payModel) { MakePayment(payModel as PayPalModel); } } public enum PaymentType { PayPalPayment = 1, CreditCardPayment = 2 } 

因此,遵循您的实现方法,它可能看起来像:

 static class Program { static void Main(object[] args) { IPaymentService paymentStrategy = null; paymentStrategy = GetPaymentOption((PaymentType)1); paymentStrategy.MakePayment(new PayPalModel { UserName = "", Password = "" }); paymentStrategy = GetPaymentOption((PaymentType)2); paymentStrategy.MakePayment(new CreditCardModel { CardHolderName = "Aakash" }); Console.ReadLine(); } private static IPaymentService GetPaymentOption(PaymentType paymentType) { switch (paymentType) { case PaymentType.PayPalPayment: return new PayPalPayment(); case PaymentType.CreditCardPayment: return new CreditCardPayment(); default: throw new NotSupportedException($"Payment Type '{paymentType.ToString()}' Not Supported"); } } } 

我也认为对于策略/工厂模式方法,手动创建IPayModel类型没有多大意义。 因此,您可以将IPaymentService扩展为IPayModel工厂:

 public interface IPaymentService { IPayModel CreatePayModel(); void MakePayment(IPayModel payModel); } public interface IPaymentService : IPaymentService where T : IPayModel { new T CreatePayModel(); void MakePayment(T payModel); } public class CreditCardPayment : IPaymentService { public CreditCardModel CreatePayModel() { return new CreditCardModel(); } public void MakePayment(CreditCardModel payModel) { //Implmentation CreditCardPayment } IPayModel IPaymentService.CreatePayModel() { return CreatePayModel(); } void IPaymentService.MakePayment(IPayModel payModel) { MakePayment(payModel as CreditCardModel); } } 

用法将是:

 IPaymentService paymentStrategy = null; paymentStrategy = GetPaymentOption((PaymentType)1); var payModel = (PayPalModel)paymentStrategy.CreatePayModel(); payModel.UserName = ""; payModel.Password = ""; paymentStrategy.MakePayment(payModel); 

您的代码基本上使用工厂模式。 这是处理多种付款方式的好方法

http://www.dotnettricks.com/learn/designpatterns/factory-method-design-pattern-dotnet

在我看来,这是一个很好地利用Strategy模式。 我会说你编写了一个名为PaymentStrategy的接口,并创建了两个具体的实现。 一个用于Paypal,另一个用于Creditcard支付。 然后,在客户端内部,您可以根据从前端传递的用户选择来确定应使用的付款策略。 然后将PaymentStrategy传递给您的context类,该类实际执行付款流程。

在上面的示例中,既不使用FactoryMethod模式,也不使用AbstractFactory模式。 我不认为这是factory模式的好候选人。

不,你在做什么不是Strategy模式。 它应该像这样改变。

 public interface PaymentStrategy { void doPayment(); } public class PaypalStrategy implements PaymentStrategy { @Override void doPayment() { // implement this. } } public class PaymentService { private final PaymentStrategy paymentStrategy; public PaymentService(PaymentStrategy paymentStrategy) { this.paymentStrategy = paymentStrategy; } public void pay() { this.paymentStrategy.doPayment(); // Do some more here. } } 

而你的客户应该是这样的。

 new PaymentService(new PaypalStrategy()).pay();