我正在尝试开发一个接口,供不同的支付处理器包装器实现使用,例如stripe,paypal等,可以注入另一个类。我遇到的问题是,每个实现很可能需要不同的数据位来处理支付,因此难以实现跨实现的通用接口。
在这种情况下,创建一个特定于每种类型处理器的接口并设计接收类以期望特定接口会更有意义吗?虽然这看起来最干净并且可以保持可测试性,但是需要重新开发接收类来实现新的处理器。
我想避免创建空接口或者为每种类型的处理器设置一个接口,并让每个实现都不会对它不需要的方法实现异常。另一种选择是使用常见的方法,例如" ChargeCard"接受一个对象,它包含每个实现所需的数据,但也感觉不对。
提前感谢您的任何帮助或建议。
答案 0 :(得分:0)
您可以这样做的一种方法是使用抽象类作为您使用的程序集中的预期父级。
IPaypal
{
//PayPal specific methods
}
IStripe
{
//Stripe specific methods
}
MyAbstractClass : IPaypal, IStripe //Other interfaces
{
//Method implementation for all of the inherited methods
}
MyPaymentClass : MyAbstractClass
{
//stuff
}
{
var payment = new MyPaymentClass();
payment.paypalMethod;
}
答案 1 :(得分:0)
这听起来像你可以使用摘要类来封装常见行为并扩展到其他类。 另一种方法是在高级创建接口,然后创建一个低级接口,扩展高级接口,然后用于您需要的每个类。
IPay{
void chargetoCard();
}
IStripe:IPay{
chargetoStripe();
}
IAnother:IPay{
void charge();
}
class Stripe:IStripe{
}
class Another:IAnother{
}
答案 2 :(得分:0)
你可以做几种模式:
访客 - 传递最低公分母。换句话说,可能会使用的所有东西然后让处理器弄明白。
Mediator - 创建一个新对象的唯一目的是找出要使用的处理器,并根据需要提供它。
如果你有时间,我最喜欢的是采取上述两个并使它们动态化,这样你只需要插入一个实现接口的插件,框架就会自动拾取并调用它。有关示例,请参阅NServiceBus或Rebus中的消息处理。这些框架接收IMessage类型的传入消息,并自动将它们提供给消息处理程序。通用界面是这样的:
public interface IMessageHandler<T> where T : IMessage
{
void Handle(T message);
}
不幸的是,我不得不自己实施这几次而不是仅使用框架,因为我不允许使用它。
你采取什么方法取决于你正在做什么 - 它有多久会改变,它只是一个原型或POC等。
绝对避免使用不会被所有人使用的方法的大型接口。
根据您的评论添加更多信息,它看起来像这样:
public interface IPaymentProcessor<T> where T : IPaymentInfo
{
void ProcessPayment(T paymentInfo);
}
// Just one example
public class CreditCardPaymentInfo : IPaymentInfo
{
public CardInfo CardInfo { get; set; }
}
public class CreditCardPaymentProcessor : IPaymentProcessor<CreditCardPaymentInfo>
{
public void ProcessPayment(CreditCardPaymentInfo paymentInfo)
{
// Do the card processing here - you have what you need
}
}
然后代码付款的某个地方就会出现,所以它会调用这样的方法:
public void ProcessCardSwipe(CardData cardData)
{
var cardInfo = new CreditCardPaymentInfo { CardInfo = cardData };
ProcessPaymetnInfo(cardInfo);
}
public void ProcessPaymetnInfo(IPaymentInfo paymentInfo)
{
// This should be refactored into a separate class, but initially to get it working this is fine
if (paymentInfo is CreditCardPaymentInfo)
{
new CreditCardPaymentProcessor().Process((paymentInfo)CreditCardPaymentInfo);
}
}