使用从网页中提取数据的服务作为示例(例如Mercury https://mercury.postlight.com/web-parser/或Diffobt https://www.diffbot.com/products/automatic/#article)我想问一个关于如何为依赖注入构造接口和类实现的问题(DI)/控制反转(IoC)场景。
我试图确定如何最好地创建IPageExtractor
接口以及随后实现MercuryPageExtractor
接口的具体实现DiffbotPageExtractor
和IPageExtractor
实际的实现是完全不同的。
显然,这是首先实现界面的全部要点,但我有心理障碍,我需要帮助过去。
例如,Mercury使用密钥和密钥进行身份验证,而Diffbot仅使用令牌。好吧也许这不是所以不同但我感到困惑的是我必须在界面中容纳这个,当然界面是最低的共同点。我是否会传递一组auth数据并让具体实现对其进行排序?
另一个不同之处是Mercury返回有关网页的3条数据,而Diffbot返回20条(这可能在技术上不准确,但可能存在差异的例子就是我所得到的)。我如何设计接口和具体实现来处理这个?
最终的显着差异在于成功与失败的构成因素在每种情况下都是非常不同的,并且因成功或失败而返回的消息类型(格式,结构,内容)也有很大差异。
你能帮忙考虑一下这个问题吗?
我在C#/ .NET工作但是以与语言无关的方式思考这个问题。
答案 0 :(得分:1)
让我们看一下界面驱动抽象工厂的另一个场景
在开始之前,我们需要明确界面指定需要要做什么,并带有输入和所需输出。 也就是说,不强制要求输入和输出都需要很好地定义,因为它们也可以作为合同本身。如果我们不完全清楚输入和输出的结构,我们可以使用标记接口;那些没有任何结构的人......
假设我们有购物车,我们需要提供付款选项。常见的选择是网上银行,信用卡和贝宝。让我们有这个场景的定义
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作为附加信息)。他们还根据自己的结构返回状态。但是,在逻辑层面,他们会获取用户的凭据,并在付款成功时返回消息
您可以将工厂设计为独立于任何其他提供商设计。只需在每个合同上设置标记接口。
在执行DI代码(例如 NInject )时,请使用" WhenInjectedInto "或类似的构造将正确的实现注入到正在使用的每个提供者中。您的工厂将根据用户的选择使用,而不会影响您的核心业务流程。
DI的主要规则是从核心中完全抽象出非核心业务。核心业务不应该关心每个提供商的期望,只是对预期的功能有一个微弱的想法。标记接口最适合此要求,尤其是在您开始设计但尚未完全清楚的情况下。您可以稍后改进标记界面,以便更清楚地了解所涉及的过程。
如果您需要进一步明确设计,请告诉我。