我对界面感到困惑吗?
本文关键字:界面 | 更新日期: 2023-09-27 18:17:34
我正在维护一个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()
中它总是使用接口。我不明白为什么使用接口而不是实现接口的类,或者它是如何工作的。是否有什么重要的东西是我的谷歌技能没有发现的?
这个特殊的设计模式通常是为了方便单元测试,因为你现在可以用一个TestOrderService代替OrderService,这两个都只被引用为IOrderService。这意味着你可以编写TestOrderService来为被测类提供特定的行为,然后感知被测类是否在做正确的事情。
在实践中,以上通常是通过使用一个mock框架来完成的,这样你就不用实际地手工编写一个TestOrderService,而是使用一个更简洁的语法来描述它在一个典型测试中的行为,然后让mock框架动态地为你生成一个实现。
至于为什么你从来没有在代码中看到'new OrderService',很可能你的项目正在使用某种形式的控制反转容器,这有助于自动依赖注入。换句话说,你不必直接构造OrderService,因为你已经在某个地方配置了IOrderService的任何使用都应该通过构造一个单例OrderService并将其传递给构造函数来自动完成。这里有很多微妙之处,我不确定你的依赖注入是如何完成的(它不一定是自动的;
这不是接口的唯一用途,在MVC中,它们被用来将契约与实现解耦。要了解MVC,您需要阅读一些相关主题,例如关注点分离和控制反转(IoC)。创建要传递给OrderService
构造函数的对象的实际行为是由IoC容器根据一些预定义的映射来处理的。
这些对象似乎不会像OrderService中OrderService = new那样直接创建OrderService ()
这样的事吗?
点是有人调用OrderService构造函数和调用者是respónsible创建他们。他把它们递给我。
我不明白为什么使用接口而不是类实现界面
因为你不想知道这个类——它可能会改变,是外部的,可以使用IOC容器进行配置,程序员决定甚至不需要一个公共基类。你对某人如何实现已使用的实用程序类的假设越少越好。
是否有一些重要的东西,我错过了界面,我的谷歌技能不是发现?
不,但是一本关于OO编程的好书会比随机的谷歌代码片段更有帮助。这基本上属于体系结构领域和。net基础(第一部分)。
针对接口而不是针对对象进行编程是很好的实践。这个问题给出了很好的理由,但是一些理由包括允许实现改变(例如为了测试)。
仅仅因为目前只有一个类实现了这个接口,并不意味着它在将来不能改变。
此外,我不明白这些是如何创建和使用的。
这被称为依赖注入,基本上意味着类不需要知道如何或从哪里实例化它的依赖,其他人会处理它。
这些是服务接口,它们封装了某种外部性。在你的主要项目中,你通常只有一个单独的实现,但是你的测试使用更简单的实现,不依赖于外部的东西。
例如,如果你的支付服务联系paypal来验证支付,你不希望在不相关代码的测试中这样做。相反,您可以将它们替换为一个简单的实现,该实现总是返回"付款工作"并检查订单流程是否完成,以及另一个返回"付款失败"并检查订单流程是否也失败的实现。
为了避免依赖于实现,您不自己创建实例,而是在构造函数中接受它们。然后,创建类的IoC容器将填充它们。查找控制反转
您的项目可能有一些在其启动代码中设置IoC容器的代码。并且该代码包含了当您想要实现某个接口时创建哪个类的信息。