我正在维护一个ASP.NET MVC项目。在该项目中,原始开发人员拥有绝对大量的接口。例如:IOrderService
,IPaymentService
,IEmailService
,IResourceService
。我感到困惑的是这些只是由一个类实现。换句话说:
OrderService : IOrderService
PaymentService : IPaymentService
我对接口的理解一直是它们用于创建一个可以轻松互换组件的架构。类似的东西:
Square : IShape
Circle : IShape
此外,我不明白这些是如何被创建和使用的。这是OrderService:
public class OrderService : IOrderService
{
private readonly ICommunicationService _communicationService;
private readonly ILogger _logger;
private readonly IRepository<Product> _productRepository;
public OrderService(ICommunicationService communicationService, ILogger logger,
IRepository<Product> productRepository)
{
_communicationService = communicationService;
_logger = logger;
_productRepository = productRepository;
}
}
这些对象似乎不会直接创建,因为OrderService orderService = new OrderService()
始终使用该接口。我不明白为什么使用接口而不是实现接口的类,或者它是如何工作的。我缺少哪些关于我的谷歌技能没有发现的界面的重要内容?
答案 0 :(得分:4)
这种特殊的设计模式通常用于促进单元测试,因为您现在可以用TestOrderService替换OrderService,这两者都只被引用为IOrderService。这意味着您可以编写TestOrderService来为被测试的类提供特定的行为,然后检测被测试的类是否正在执行正确的操作。
实际上,上面通常是通过使用Mocking框架来完成的,因此您实际上并不手动编写TestOrderService代码,而是使用更简洁的语法来描述它应该如何处理典型测试,然后具有模拟框架为您动态生成实现。
至于为什么你从未在代码中看到'new OrderService',你的项目可能正在使用某种形式的Inversion of Control容器,这有利于自动依赖注入。换句话说,您不必直接构造OrderService,因为您已经配置了通过构造单个OrderService并将其传递给构造函数来自动满足任何IOrderService使用的地方。这里有很多细微之处,我不确定你的依赖注入是如何完成的(它不必是自动的;你也可以手动构造实例并通过构造函数传递它们。)
答案 1 :(得分:1)
这不是接口的唯一用途,在MVC中它们被用于将合同与实现分离。要了解MVC,您需要阅读相关主题,例如关注点分离和控制反转(IoC)。创建要传递给OrderService
构造函数的对象的实际行为由IoC容器处理基于一些预定义的映射。
答案 2 :(得分:1)
似乎没有像OrderService orderService = new那样直接创建这些对象 OrderService()
那么呢?
重点是SOMEONE调用OrderService构造函数,而CALLER可以重新创建它们。他把它们交给了他们。
我不明白为什么要使用接口而不是实现接口的类 接口
因为你不想知道这个类 - 它可能会改变,在外部,可以使用IOC容器进行配置,程序员决定不需要甚至是一个公共基类。关于某人如何实现使用过的实用程序类的假设越少越好。
我缺少一些关于我的谷歌技能不具备的界面的重要内容 揭开?
不,一本关于面向对象编程的好书会比随机的谷歌片段更有帮助。这个基础上属于架构领域和.NET基础(第一部分)。
答案 3 :(得分:1)
对接口而不是对象进行编程是一种很好的做法。 This问题给出了很好的理由,但有些原因包括允许实施改变(例如测试)。
仅仅因为目前只有一个实现接口的类并不意味着它将来不会改变。
此外,我不明白这些是如何被创造和使用的。
这称为dependency injection,基本上意味着该类不需要知道如何或在何处实例化它的依赖关系,其他人将处理它。
答案 4 :(得分:0)
这些是服务接口,它封装了某种外部性。您通常在主项目中只有一个实现它们,但您的测试使用不依赖于外部内容的更简单的实现。
例如,如果您的付款服务与paypal联系以验证付款,则您不希望在不相关代码的测试中执行此操作。相反,您可以使用一个简单的实现来替换它们,这个实现始终返回“付费工作”并检查订单流程是否完成,另一个实现返回“付款失败”并检查订单流程是否也失败。
为了避免依赖于实现,您不自己创建实例,您在构造函数中接受它们。然后,创建类的IoC容器将填充它们。查找Inversion of Control。
您的项目可能有一些代码在其启动代码中设置了IoC容器。并且该代码包含有关在需要实现某个接口时要创建的类的信息。