接口的设计过程和 类 在实现如此不同的情况下用于依赖注入场景

Design process for interfaces and classes used in dependency injection scenarios when implementations are so different

以从网页中提取数据的服务为例(例如Mercuryhttps://mercury.postlight.com/web-parser/ or Diffobt https://www.diffbot.com/products/automatic/#article)我想问一个关于如何构建接口和class实现的问题依赖注入 (DI)/控制反转 (IoC) 场景。

鉴于实际实现是完全不同的。

显然,这首先是实现接口的全部要点,但我遇到了心理障碍,需要帮助才能克服。

例如,Mercury 使用密钥和秘密进行身份验证,而 Diffbot 仅使用令牌。好吧,也许这不是 so 不同,但我感到困惑的地方是我必须在界面中容纳它,当然界面是最低公分母。例如,我会传入一组身份验证数据并让具体实现对其进行分类吗?

另一个不同是 Mercury returns 3 条关于网页的数据,而 Diffbot returns 像 20 条(这在技术上可能不准确,但可能存在差异的示例是我在说什么)。我将如何设计接口和具体实现来处理这个问题?

最后一个显着差异是,在每种情况下,成功和失败的构成因素非常不同,成功或失败返回的消息类型(格式、结构、内容)也大不相同。

能不能请大家帮忙想想这个问题?

我在 C#/.NET 中工作,但以独立于语言的方式思考这个问题。

让我们来看看接口驱动抽象工厂的另一个场景

在开始之前,我们需要明确一个接口指定了需要做什么,并微妙地指示输入和期望输出。 也就是说,它 并不 强制输入和输出都需要明确定义,因为它们也可以作为合同本身。如果我们不完全清楚输入和输出的结构是什么,我们可以使用marker interfaces;那些根本没有任何结构的..

假设我们有一个购物车,我们需要提供付款选项。常见的选择是网上银行、信用卡和贝宝。让我们定义这个场景

public interface ICustomerAccountInformation {  }

public interface IPaymentClient {  }  // Identifies whom the payment is intended for

public interface ITransactionDetails : IPaymentClient {  }  // Identifies amount, beneficiary details to be reflected in customer account

public interface IPaymentStatus { }

public interface IPaymentProvider  { 
    IPaymentStatus ProcessPayment(ICustomerAccountInformation customerInfo, ITransactionDetails transaction);

}


public class PayPal : IPaymentProvider  {

    public IPaymentStatus ProcessPayment(ICustomerAccountInformation customerInfo, ITransactionDetails transaction)  {
           /* Open paypal's login page, 
             do its own checks and process payment. 
             Once successfull, send back to referrer with the payment status
           */
    }

public class NetbankingProvider : IPaymentProvider  {

    public IPaymentStatus ProcessPayment(ICustomerAccountInformation customerInfo, ITransactionDetails transaction)  {
           /* Redirect to bank selection
             redirect to bank's login page, 
             do its own checks and process payment. 
             Once successfull, send back to referrer with the payment status
           */
    }

在整个流程中,每个提供者都可以自由询问所需的任何信息(有些只接受凭据,而另一些则要求提供 OTP 作为附加信息)。他们还 return 根据自己的结构返回状态。但是,在逻辑层面上,他们会获取用户的凭据,并 return 返回一条消息,判断付款是否成功

您可以将工厂设计为独立于任何其他提供程序设计。只需在每个合约上设置标记接口。

在执行 DI 代码时(比如 NInject),使用“WhenInjectedInto”或类似的构造来注入正确实施到每个正在使用的提供者中。您的工厂将根据用户的选择可供使用,而不会影响您的核心业务流程。

DI 的主要规则是从核心业务中完全抽象出非核心业务。核心业务不应该关心每个提供者期望什么,只是对期望的功能有一个模糊的想法。标记界面最适合这个要求,尤其是当你已经开始设计但还不是很清楚的时候。随着您对所涉及的过程更加清晰,您可以稍后改进标记界面。

如果您需要进一步了解设计,请告诉我。